Add contact form checkbox in admin form
This commit is contained in:
parent
a4101923e6
commit
3866f1a02f
|
@ -7,169 +7,169 @@
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Instance</div>
|
<div i18n class="inner-form-title">Instance</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="instance">
|
||||||
<label i18n for="instanceName">Name</label>
|
<div class="form-group">
|
||||||
<input
|
<label i18n for="instanceName">Name</label>
|
||||||
type="text" id="instanceName"
|
<input
|
||||||
formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }"
|
type="text" id="instanceName"
|
||||||
>
|
formControlName="name" [ngClass]="{ 'input-error': formErrors.instance.name }"
|
||||||
<div *ngIf="formErrors.instanceName" class="form-error">
|
>
|
||||||
{{ formErrors.instanceName }}
|
<div *ngIf="formErrors.instance.name" class="form-error">{{ formErrors.instance.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="instanceShortDescription">Short description</label>
|
<label i18n for="instanceShortDescription">Short description</label>
|
||||||
<textarea
|
<textarea
|
||||||
id="instanceShortDescription" formControlName="instanceShortDescription"
|
id="instanceShortDescription" formControlName="shortDescription"
|
||||||
[ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
|
[ngClass]="{ 'input-error': formErrors['instance.shortDescription'] }"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div *ngIf="formErrors.instanceShortDescription" class="form-error">
|
<div *ngIf="formErrors.instance.shortDescription" class="form-error">{{ formErrors.instance.shortDescription }}</div>
|
||||||
{{ formErrors.instanceShortDescription }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
|
<label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
|
||||||
<my-markdown-textarea
|
<my-markdown-textarea
|
||||||
id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true"
|
id="instanceDescription" formControlName="description" textareaWidth="500px" [previewColumn]="true"
|
||||||
[classes]="{ 'input-error': formErrors['instanceDescription'] }"
|
[classes]="{ 'input-error': formErrors['instance.description'] }"
|
||||||
></my-markdown-textarea>
|
></my-markdown-textarea>
|
||||||
<div *ngIf="formErrors.instanceDescription" class="form-error">
|
<div *ngIf="formErrors.instance.description" class="form-error">{{ formErrors.instance.description }}</div>
|
||||||
{{ formErrors.instanceDescription }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
|
<label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
|
||||||
<my-markdown-textarea
|
<my-markdown-textarea
|
||||||
id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true"
|
id="instanceTerms" formControlName="terms" textareaWidth="500px" [previewColumn]="true"
|
||||||
[ngClass]="{ 'input-error': formErrors['instanceTerms'] }"
|
[ngClass]="{ 'input-error': formErrors['instance.terms'] }"
|
||||||
></my-markdown-textarea>
|
></my-markdown-textarea>
|
||||||
<div *ngIf="formErrors.instanceTerms" class="form-error">
|
<div *ngIf="formErrors.instance.terms" class="form-error">{{ formErrors.instance.terms }}</div>
|
||||||
{{ formErrors.instanceTerms }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="instanceDefaultClientRoute">Default client route</label>
|
<label i18n for="instanceDefaultClientRoute">Default client route</label>
|
||||||
<div class="peertube-select-container">
|
<div class="peertube-select-container">
|
||||||
<select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
|
<select id="instanceDefaultClientRoute" formControlName="defaultClientRoute">
|
||||||
<option i18n value="/videos/overview">Videos Overview</option>
|
<option i18n value="/videos/overview">Videos Overview</option>
|
||||||
<option i18n value="/videos/trending">Videos Trending</option>
|
<option i18n value="/videos/trending">Videos Trending</option>
|
||||||
<option i18n value="/videos/recently-added">Videos Recently Added</option>
|
<option i18n value="/videos/recently-added">Videos Recently Added</option>
|
||||||
<option i18n value="/videos/local">Local videos</option>
|
<option i18n value="/videos/local">Local videos</option>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="formErrors.instance.defaultClientRoute" class="form-error">{{ formErrors.instance.defaultClientRoute }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error">
|
|
||||||
{{ formErrors.instanceDefaultClientRoute }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
|
<label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
|
||||||
<my-help
|
<my-help
|
||||||
helpType="custom" i18n-customHtml
|
helpType="custom" i18n-customHtml
|
||||||
customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."
|
customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."
|
||||||
></my-help>
|
></my-help>
|
||||||
|
|
||||||
<div class="peertube-select-container">
|
<div class="peertube-select-container">
|
||||||
<select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy">
|
<select id="instanceDefaultNSFWPolicy" formControlName="defaultNSFWPolicy">
|
||||||
<option i18n value="do_not_list">Do not list</option>
|
<option i18n value="do_not_list">Do not list</option>
|
||||||
<option i18n value="blur">Blur thumbnails</option>
|
<option i18n value="blur">Blur thumbnails</option>
|
||||||
<option i18n value="display">Display</option>
|
<option i18n value="display">Display</option>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="formErrors.instance.defaultNSFWPolicy" class="form-error">{{ formErrors.instance.defaultNSFWPolicy }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error">
|
</ng-container>
|
||||||
{{ formErrors.instanceDefaultNSFWPolicy }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Signup</div>
|
<div i18n class="inner-form-title">Signup</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="signup">
|
||||||
<my-peertube-checkbox
|
<div class="form-group">
|
||||||
inputName="signupEnabled" formControlName="signupEnabled"
|
<my-peertube-checkbox
|
||||||
i18n-labelText labelText="Signup enabled"
|
inputName="signupEnabled" formControlName="enabled"
|
||||||
></my-peertube-checkbox>
|
i18n-labelText labelText="Signup enabled"
|
||||||
</div>
|
></my-peertube-checkbox>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<my-peertube-checkbox *ngIf="isSignupEnabled()"
|
|
||||||
inputName="signupRequiresEmailVerification" formControlName="signupRequiresEmailVerification"
|
|
||||||
i18n-labelText labelText="Signup requires email verification"
|
|
||||||
></my-peertube-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="isSignupEnabled()" class="form-group">
|
|
||||||
<label i18n for="signupLimit">Signup limit</label>
|
|
||||||
<input
|
|
||||||
type="text" id="signupLimit"
|
|
||||||
formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }"
|
|
||||||
>
|
|
||||||
<div *ngIf="formErrors.signupLimit" class="form-error">
|
|
||||||
{{ formErrors.signupLimit }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Import</div>
|
<div class="form-group">
|
||||||
|
<my-peertube-checkbox *ngIf="isSignupEnabled()"
|
||||||
<div class="form-group">
|
inputName="signupRequiresEmailVerification" formControlName="requiresEmailVerification"
|
||||||
<my-peertube-checkbox
|
i18n-labelText labelText="Signup requires email verification"
|
||||||
inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled"
|
></my-peertube-checkbox>
|
||||||
i18n-labelText labelText="Video import with HTTP URL (i.e. YouTube) enabled"
|
|
||||||
></my-peertube-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<my-peertube-checkbox
|
|
||||||
inputName="importVideosTorrentEnabled" formControlName="importVideosTorrentEnabled"
|
|
||||||
i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled"
|
|
||||||
></my-peertube-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Administrator</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label i18n for="adminEmail">Admin email</label>
|
|
||||||
<input
|
|
||||||
type="text" id="adminEmail"
|
|
||||||
formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }"
|
|
||||||
>
|
|
||||||
<div *ngIf="formErrors.adminEmail" class="form-error">
|
|
||||||
{{ formErrors.adminEmail }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div *ngIf="isSignupEnabled()" class="form-group">
|
||||||
|
<label i18n for="signupLimit">Signup limit</label>
|
||||||
|
<input
|
||||||
|
type="text" id="signupLimit"
|
||||||
|
formControlName="limit" [ngClass]="{ 'input-error': formErrors['signup.limit'] }"
|
||||||
|
>
|
||||||
|
<div *ngIf="formErrors.signup.limit" class="form-error">{{ formErrors.signup.limit }}</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Users</div>
|
<div i18n class="inner-form-title">Users</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="user">
|
||||||
<label i18n for="userVideoQuota">User default video quota</label>
|
<div class="form-group">
|
||||||
<div class="peertube-select-container">
|
<label i18n for="userVideoQuota">User default video quota</label>
|
||||||
<select id="userVideoQuota" formControlName="userVideoQuota">
|
<div class="peertube-select-container">
|
||||||
<option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
|
<select id="userVideoQuota" formControlName="videoQuota">
|
||||||
{{ videoQuotaOption.label }}
|
<option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
|
||||||
</option>
|
{{ videoQuotaOption.label }}
|
||||||
</select>
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="formErrors.user.videoQuota" class="form-error">{{ formErrors.user.videoQuota }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="formErrors.userVideoQuota" class="form-error">
|
|
||||||
{{ formErrors.userVideoQuota }}
|
<div class="form-group">
|
||||||
|
<label i18n for="userVideoQuotaDaily">User default daily upload limit</label>
|
||||||
|
<div class="peertube-select-container">
|
||||||
|
<select id="userVideoQuotaDaily" formControlName="videoQuotaDaily">
|
||||||
|
<option *ngFor="let videoQuotaDailyOption of videoQuotaDailyOptions" [value]="videoQuotaDailyOption.value">
|
||||||
|
{{ videoQuotaDailyOption.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="formErrors.user.videoQuotaDaily" class="form-error">{{ formErrors.user.videoQuotaDaily }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<div i18n class="inner-form-title">Import</div>
|
||||||
|
|
||||||
|
<ng-container formGroupName="import">
|
||||||
|
<ng-container formGroupName="videos">
|
||||||
|
|
||||||
|
<div class="form-group" formGroupName="http">
|
||||||
|
<my-peertube-checkbox
|
||||||
|
inputName="importVideosHttpEnabled" formControlName="enabled"
|
||||||
|
i18n-labelText labelText="Video import with HTTP URL (i.e. YouTube) enabled"
|
||||||
|
></my-peertube-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" formGroupName="torrent">
|
||||||
|
<my-peertube-checkbox
|
||||||
|
inputName="importVideosTorrentEnabled" formControlName="enabled"
|
||||||
|
i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled"
|
||||||
|
></my-peertube-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<div i18n class="inner-form-title">Administrator</div>
|
||||||
|
|
||||||
|
<div class="form-group" formGroupName="admin">
|
||||||
|
<label i18n for="adminEmail">Admin email</label>
|
||||||
|
<input
|
||||||
|
type="text" id="adminEmail"
|
||||||
|
formControlName="email" [ngClass]="{ 'input-error': formErrors['admin.email'] }"
|
||||||
|
>
|
||||||
|
<div *ngIf="formErrors.admin.email" class="form-error">{{ formErrors.admin.email }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group" formGroupName="contactForm">
|
||||||
<label i18n for="userVideoQuotaDaily">User default daily upload limit</label>
|
<my-peertube-checkbox
|
||||||
<div class="peertube-select-container">
|
inputName="enableContactForm" formControlName="enabled"
|
||||||
<select id="userVideoQuotaDaily" formControlName="userVideoQuotaDaily">
|
i18n-labelText labelText="Enable contact form"
|
||||||
<option *ngFor="let videoQuotaDailyOption of videoQuotaDailyOptions" [value]="videoQuotaDailyOption.value">
|
></my-peertube-checkbox>
|
||||||
{{ videoQuotaDailyOption.label }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="formErrors.userVideoQuotaDaily" class="form-error">
|
|
||||||
{{ formErrors.userVideoQuotaDaily }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
|
|
||||||
|
@ -177,30 +177,35 @@
|
||||||
<ng-template ngbTabContent>
|
<ng-template ngbTabContent>
|
||||||
<div i18n class="inner-form-title">Twitter</div>
|
<div i18n class="inner-form-title">Twitter</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="services">
|
||||||
<label i18n for="signupLimit">Your Twitter username</label>
|
<ng-container formGroupName="twitter">
|
||||||
<my-help
|
|
||||||
helpType="custom" i18n-customHtml
|
<div class="form-group">
|
||||||
customHtml="Indicates the Twitter account for the website or platform on which the content was published."
|
<label i18n for="signupLimit">Your Twitter username</label>
|
||||||
></my-help>
|
<my-help
|
||||||
<input
|
helpType="custom" i18n-customHtml
|
||||||
type="text" id="servicesTwitterUsername"
|
customHtml="Indicates the Twitter account for the website or platform on which the content was published."
|
||||||
formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }"
|
></my-help>
|
||||||
>
|
<input
|
||||||
<div *ngIf="formErrors.servicesTwitterUsername" class="form-error">
|
type="text" id="servicesTwitterUsername"
|
||||||
{{ formErrors.servicesTwitterUsername }}
|
formControlName="username" [ngClass]="{ 'input-error': formErrors['services.twitter.username'] }"
|
||||||
</div>
|
>
|
||||||
</div>
|
<div *ngIf="formErrors.services.twitter.username" class="form-error">{{ formErrors.services.twitter.username }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<my-peertube-checkbox
|
||||||
|
inputName="servicesTwitterWhitelisted" formControlName="whitelisted"
|
||||||
|
i18n-labelText labelText="Instance whitelisted by Twitter"
|
||||||
|
i18n-helpHtml helpHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
|
||||||
|
If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
|
||||||
|
Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."
|
||||||
|
></my-peertube-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<my-peertube-checkbox
|
|
||||||
inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted"
|
|
||||||
i18n-labelText labelText="Instance whitelisted by Twitter"
|
|
||||||
i18n-helpHtml helpHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
|
|
||||||
If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
|
|
||||||
Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."
|
|
||||||
></my-peertube-checkbox>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
|
|
||||||
|
@ -209,45 +214,48 @@
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Transcoding</div>
|
<div i18n class="inner-form-title">Transcoding</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="transcoding">
|
||||||
<my-peertube-checkbox
|
|
||||||
inputName="transcodingEnabled" formControlName="transcodingEnabled"
|
|
||||||
i18n-labelText labelText="Transcoding enabled"
|
|
||||||
i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!"
|
|
||||||
></my-peertube-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-template [ngIf]="isTranscodingEnabled()">
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<my-peertube-checkbox
|
<my-peertube-checkbox
|
||||||
inputName="transcodingAllowAdditionalExtensions" formControlName="transcodingAllowAdditionalExtensions"
|
inputName="transcodingEnabled" formControlName="enabled"
|
||||||
i18n-labelText labelText="Allow additional extensions"
|
i18n-labelText labelText="Transcoding enabled"
|
||||||
i18n-helpHtml helpHtml="Allow your users to upload .mkv, .mov, .avi, .flv videos"
|
i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!"
|
||||||
></my-peertube-checkbox>
|
></my-peertube-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container *ngIf="isTranscodingEnabled()">
|
||||||
<label i18n for="transcodingThreads">Transcoding threads</label>
|
|
||||||
<div class="peertube-select-container">
|
|
||||||
<select id="transcodingThreads" formControlName="transcodingThreads">
|
|
||||||
<option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
|
|
||||||
{{ transcodingThreadOption.label }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="formErrors.transcodingThreads" class="form-error">
|
|
||||||
{{ formErrors.transcodingThreads }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" *ngFor="let resolution of resolutions">
|
<div class="form-group">
|
||||||
<my-peertube-checkbox
|
<my-peertube-checkbox
|
||||||
[inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)"
|
inputName="transcodingAllowAdditionalExtensions" formControlName="allowAdditionalExtensions"
|
||||||
i18n-labelText labelText="Resolution {{resolution}} enabled"
|
i18n-labelText labelText="Allow additional extensions"
|
||||||
></my-peertube-checkbox>
|
i18n-helpHtml helpHtml="Allow your users to upload .mkv, .mov, .avi, .flv videos"
|
||||||
</div>
|
></my-peertube-checkbox>
|
||||||
</ng-template>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label i18n for="transcodingThreads">Transcoding threads</label>
|
||||||
|
<div class="peertube-select-container">
|
||||||
|
<select id="transcodingThreads" formControlName="threads">
|
||||||
|
<option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
|
||||||
|
{{ transcodingThreadOption.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="formErrors.transcoding.threads" class="form-error">{{ formErrors.transcoding.threads }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container formGroupName="resolutions">
|
||||||
|
<div class="form-group" *ngFor="let resolution of resolutions">
|
||||||
|
<my-peertube-checkbox
|
||||||
|
[inputName]="getResolutionKey(resolution)" [formControlName]="resolution"
|
||||||
|
i18n-labelText labelText="Resolution {{resolution}} enabled"
|
||||||
|
></my-peertube-checkbox>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<div i18n class="inner-form-title">
|
<div i18n class="inner-form-title">
|
||||||
Cache
|
Cache
|
||||||
|
@ -258,74 +266,73 @@
|
||||||
></my-help>
|
></my-help>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="cache">
|
||||||
<label i18n for="cachePreviewsSize">Previews cache size</label>
|
<div class="form-group" formGroupName="previews">
|
||||||
<input
|
<label i18n for="cachePreviewsSize">Previews cache size</label>
|
||||||
type="text" id="cachePreviewsSize"
|
<input
|
||||||
formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }"
|
type="text" id="cachePreviewsSize"
|
||||||
>
|
formControlName="size" [ngClass]="{ 'input-error': formErrors['cache.previews.size'] }"
|
||||||
<div *ngIf="formErrors.cachePreviewsSize" class="form-error">
|
>
|
||||||
{{ formErrors.cachePreviewsSize }}
|
<div *ngIf="formErrors.cache.previews.size" class="form-error">{{ formErrors.cache.previews.size }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group" formGroupName="captions">
|
||||||
<label i18n for="cachePreviewsSize">Video captions cache size</label>
|
<label i18n for="cacheCaptionsSize">Video captions cache size</label>
|
||||||
<input
|
<input
|
||||||
type="text" id="cacheCaptionsSize"
|
type="text" id="cacheCaptionsSize"
|
||||||
formControlName="cacheCaptionsSize" [ngClass]="{ 'input-error': formErrors['cacheCaptionsSize'] }"
|
formControlName="size" [ngClass]="{ 'input-error': formErrors['cache.captions.size'] }"
|
||||||
>
|
>
|
||||||
<div *ngIf="formErrors.cacheCaptionsSize" class="form-error">
|
<div *ngIf="formErrors.cache.captions.size" class="form-error">{{ formErrors.cache.captions.size }}</div>
|
||||||
{{ formErrors.cacheCaptionsSize }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
|
|
||||||
<div i18n class="inner-form-title">Customizations</div>
|
<div i18n class="inner-form-title">Customizations</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<ng-container formGroupName="instance">
|
||||||
<label i18n for="customizationJavascript">JavaScript</label>
|
<ng-container formGroupName="customizations">
|
||||||
<my-help
|
<div class="form-group">
|
||||||
helpType="custom" i18n-customHtml
|
<label i18n for="customizationJavascript">JavaScript</label>
|
||||||
customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"
|
<my-help
|
||||||
></my-help>
|
helpType="custom" i18n-customHtml
|
||||||
<textarea
|
customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"
|
||||||
id="customizationJavascript" formControlName="customizationJavascript"
|
></my-help>
|
||||||
[ngClass]="{ 'input-error': formErrors['customizationJavascript'] }"
|
<textarea
|
||||||
></textarea>
|
id="customizationJavascript" formControlName="javascript"
|
||||||
<div *ngIf="formErrors.customizationJavascript" class="form-error">
|
[ngClass]="{ 'input-error': formErrors['instance.customizations.javascript'] }"
|
||||||
{{ formErrors.customizationJavascript }}
|
></textarea>
|
||||||
</div>
|
<div *ngIf="formErrors.instance.customizations.javascript" class="form-error">{{ formErrors.instance.customizations.javascript }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="customizationCSS">CSS</label>
|
<label for="customizationCSS">CSS</label>
|
||||||
<my-help
|
<my-help
|
||||||
helpType="custom"
|
helpType="custom"
|
||||||
i18n-customHtml
|
i18n-customHtml
|
||||||
customHtml="
|
customHtml="
|
||||||
Write directly CSS code. Example:<br />
|
Write directly CSS code. Example:<br />
|
||||||
<pre>
|
<pre>
|
||||||
body {{ '{' }}
|
body {{ '{' }}
|
||||||
background-color: red;
|
background-color: red;
|
||||||
{{ '}' }}
|
{{ '}' }}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
Prepend with <em>#custom-css</em> to override styles. Example:
|
||||||
|
<pre>
|
||||||
|
#custom-css .logged-in-email {{ '{' }}
|
||||||
|
color: red;
|
||||||
|
{{ '}' }}
|
||||||
|
</pre>
|
||||||
|
"
|
||||||
|
></my-help>
|
||||||
|
<textarea
|
||||||
|
id="customizationCSS" formControlName="css"
|
||||||
|
[ngClass]="{ 'input-error': formErrors['instance.customizations.css'] }"
|
||||||
|
></textarea>
|
||||||
|
<div *ngIf="formErrors.instance.customizations.css" class="form-error">{{ formErrors.instance.customizations.css }}</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
Prepend with <em>#custom-css</em> to override styles. Example:
|
|
||||||
<pre>
|
|
||||||
#custom-css .logged-in-email {{ '{' }}
|
|
||||||
color: red;
|
|
||||||
{{ '}' }}
|
|
||||||
</pre>
|
|
||||||
"
|
|
||||||
></my-help>
|
|
||||||
<textarea
|
|
||||||
id="customizationCSS" formControlName="customizationCSS"
|
|
||||||
[ngClass]="{ 'input-error': formErrors['customizationCSS'] }"
|
|
||||||
></textarea>
|
|
||||||
<div *ngIf="formErrors.customizationCSS" class="form-error">
|
|
||||||
{{ formErrors.customizationCSS }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
</ngb-tabset>
|
</ngb-tabset>
|
||||||
|
|
|
@ -18,9 +18,6 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
resolutions: string[] = []
|
resolutions: string[] = []
|
||||||
transcodingThreadOptions: { label: string, value: number }[] = []
|
transcodingThreadOptions: { label: string, value: number }[] = []
|
||||||
|
|
||||||
private oldCustomJavascript: string
|
|
||||||
private oldCustomCSS: string
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
protected formValidatorService: FormValidatorService,
|
protected formValidatorService: FormValidatorService,
|
||||||
private customConfigValidatorsService: CustomConfigValidatorsService,
|
private customConfigValidatorsService: CustomConfigValidatorsService,
|
||||||
|
@ -58,41 +55,78 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
getResolutionKey (resolution: string) {
|
getResolutionKey (resolution: string) {
|
||||||
return 'transcodingResolution' + resolution
|
return 'transcoding.resolutions.' + resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
const formGroupData: { [key: string]: any } = {
|
const formGroupData: { [key in keyof CustomConfig ]: any } = {
|
||||||
instanceName: this.customConfigValidatorsService.INSTANCE_NAME,
|
instance: {
|
||||||
instanceShortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
|
name: this.customConfigValidatorsService.INSTANCE_NAME,
|
||||||
instanceDescription: null,
|
shortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
|
||||||
instanceTerms: null,
|
description: null,
|
||||||
instanceDefaultClientRoute: null,
|
terms: null,
|
||||||
instanceDefaultNSFWPolicy: null,
|
defaultClientRoute: null,
|
||||||
servicesTwitterUsername: this.customConfigValidatorsService.SERVICES_TWITTER_USERNAME,
|
defaultNSFWPolicy: null,
|
||||||
servicesTwitterWhitelisted: null,
|
customizations: {
|
||||||
cachePreviewsSize: this.customConfigValidatorsService.CACHE_PREVIEWS_SIZE,
|
javascript: null,
|
||||||
cacheCaptionsSize: this.customConfigValidatorsService.CACHE_CAPTIONS_SIZE,
|
css: null
|
||||||
signupEnabled: null,
|
}
|
||||||
signupLimit: this.customConfigValidatorsService.SIGNUP_LIMIT,
|
},
|
||||||
signupRequiresEmailVerification: null,
|
services: {
|
||||||
importVideosHttpEnabled: null,
|
twitter: {
|
||||||
importVideosTorrentEnabled: null,
|
username: this.customConfigValidatorsService.SERVICES_TWITTER_USERNAME,
|
||||||
adminEmail: this.customConfigValidatorsService.ADMIN_EMAIL,
|
whitelisted: null
|
||||||
userVideoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
|
}
|
||||||
userVideoQuotaDaily: this.userValidatorsService.USER_VIDEO_QUOTA_DAILY,
|
},
|
||||||
transcodingThreads: this.customConfigValidatorsService.TRANSCODING_THREADS,
|
cache: {
|
||||||
transcodingAllowAdditionalExtensions: null,
|
previews: {
|
||||||
transcodingEnabled: null,
|
size: this.customConfigValidatorsService.CACHE_PREVIEWS_SIZE
|
||||||
customizationJavascript: null,
|
},
|
||||||
customizationCSS: null
|
captions: {
|
||||||
|
size: this.customConfigValidatorsService.CACHE_CAPTIONS_SIZE
|
||||||
|
}
|
||||||
|
},
|
||||||
|
signup: {
|
||||||
|
enabled: null,
|
||||||
|
limit: this.customConfigValidatorsService.SIGNUP_LIMIT,
|
||||||
|
requiresEmailVerification: null
|
||||||
|
},
|
||||||
|
import: {
|
||||||
|
videos: {
|
||||||
|
http: {
|
||||||
|
enabled: null
|
||||||
|
},
|
||||||
|
torrent: {
|
||||||
|
enabled: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
email: this.customConfigValidatorsService.ADMIN_EMAIL
|
||||||
|
},
|
||||||
|
contactForm: {
|
||||||
|
enabled: null
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
videoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
|
||||||
|
videoQuotaDaily: this.userValidatorsService.USER_VIDEO_QUOTA_DAILY
|
||||||
|
},
|
||||||
|
transcoding: {
|
||||||
|
enabled: null,
|
||||||
|
threads: this.customConfigValidatorsService.TRANSCODING_THREADS,
|
||||||
|
allowAdditionalExtensions: null,
|
||||||
|
resolutions: {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultValues: BuildFormDefaultValues = {}
|
const defaultValues = {
|
||||||
|
transcoding: {
|
||||||
|
resolutions: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const resolution of this.resolutions) {
|
for (const resolution of this.resolutions) {
|
||||||
const key = this.getResolutionKey(resolution)
|
defaultValues.transcoding.resolutions[resolution] = 'false'
|
||||||
defaultValues[key] = 'false'
|
formGroupData.transcoding.resolutions[resolution] = null
|
||||||
formGroupData[key] = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buildForm(formGroupData)
|
this.buildForm(formGroupData)
|
||||||
|
@ -102,9 +136,6 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
res => {
|
res => {
|
||||||
this.customConfig = res
|
this.customConfig = res
|
||||||
|
|
||||||
this.oldCustomCSS = this.customConfig.instance.customizations.css
|
|
||||||
this.oldCustomJavascript = this.customConfig.instance.customizations.javascript
|
|
||||||
|
|
||||||
this.updateForm()
|
this.updateForm()
|
||||||
// Force form validation
|
// Force form validation
|
||||||
this.forceCheck()
|
this.forceCheck()
|
||||||
|
@ -115,78 +146,15 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
isTranscodingEnabled () {
|
isTranscodingEnabled () {
|
||||||
return this.form.value['transcodingEnabled'] === true
|
return this.form.value['transcoding']['enabled'] === true
|
||||||
}
|
}
|
||||||
|
|
||||||
isSignupEnabled () {
|
isSignupEnabled () {
|
||||||
return this.form.value['signupEnabled'] === true
|
return this.form.value['signup']['enabled'] === true
|
||||||
}
|
}
|
||||||
|
|
||||||
async formValidated () {
|
async formValidated () {
|
||||||
const data: CustomConfig = {
|
this.configService.updateCustomConfig(this.form.value)
|
||||||
instance: {
|
|
||||||
name: this.form.value['instanceName'],
|
|
||||||
shortDescription: this.form.value['instanceShortDescription'],
|
|
||||||
description: this.form.value['instanceDescription'],
|
|
||||||
terms: this.form.value['instanceTerms'],
|
|
||||||
defaultClientRoute: this.form.value['instanceDefaultClientRoute'],
|
|
||||||
defaultNSFWPolicy: this.form.value['instanceDefaultNSFWPolicy'],
|
|
||||||
customizations: {
|
|
||||||
javascript: this.form.value['customizationJavascript'],
|
|
||||||
css: this.form.value['customizationCSS']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
services: {
|
|
||||||
twitter: {
|
|
||||||
username: this.form.value['servicesTwitterUsername'],
|
|
||||||
whitelisted: this.form.value['servicesTwitterWhitelisted']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cache: {
|
|
||||||
previews: {
|
|
||||||
size: this.form.value['cachePreviewsSize']
|
|
||||||
},
|
|
||||||
captions: {
|
|
||||||
size: this.form.value['cacheCaptionsSize']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
signup: {
|
|
||||||
enabled: this.form.value['signupEnabled'],
|
|
||||||
limit: this.form.value['signupLimit'],
|
|
||||||
requiresEmailVerification: this.form.value['signupRequiresEmailVerification']
|
|
||||||
},
|
|
||||||
admin: {
|
|
||||||
email: this.form.value['adminEmail']
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
videoQuota: this.form.value['userVideoQuota'],
|
|
||||||
videoQuotaDaily: this.form.value['userVideoQuotaDaily']
|
|
||||||
},
|
|
||||||
transcoding: {
|
|
||||||
enabled: this.form.value['transcodingEnabled'],
|
|
||||||
allowAdditionalExtensions: this.form.value['transcodingAllowAdditionalExtensions'],
|
|
||||||
threads: this.form.value['transcodingThreads'],
|
|
||||||
resolutions: {
|
|
||||||
'240p': this.form.value[this.getResolutionKey('240p')],
|
|
||||||
'360p': this.form.value[this.getResolutionKey('360p')],
|
|
||||||
'480p': this.form.value[this.getResolutionKey('480p')],
|
|
||||||
'720p': this.form.value[this.getResolutionKey('720p')],
|
|
||||||
'1080p': this.form.value[this.getResolutionKey('1080p')]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
import: {
|
|
||||||
videos: {
|
|
||||||
http: {
|
|
||||||
enabled: this.form.value['importVideosHttpEnabled']
|
|
||||||
},
|
|
||||||
torrent: {
|
|
||||||
enabled: this.form.value['importVideosTorrentEnabled']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.configService.updateCustomConfig(data)
|
|
||||||
.subscribe(
|
.subscribe(
|
||||||
res => {
|
res => {
|
||||||
this.customConfig = res
|
this.customConfig = res
|
||||||
|
@ -204,38 +172,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateForm () {
|
private updateForm () {
|
||||||
const data: { [key: string]: any } = {
|
this.form.patchValue(this.customConfig)
|
||||||
instanceName: this.customConfig.instance.name,
|
|
||||||
instanceShortDescription: this.customConfig.instance.shortDescription,
|
|
||||||
instanceDescription: this.customConfig.instance.description,
|
|
||||||
instanceTerms: this.customConfig.instance.terms,
|
|
||||||
instanceDefaultClientRoute: this.customConfig.instance.defaultClientRoute,
|
|
||||||
instanceDefaultNSFWPolicy: this.customConfig.instance.defaultNSFWPolicy,
|
|
||||||
servicesTwitterUsername: this.customConfig.services.twitter.username,
|
|
||||||
servicesTwitterWhitelisted: this.customConfig.services.twitter.whitelisted,
|
|
||||||
cachePreviewsSize: this.customConfig.cache.previews.size,
|
|
||||||
cacheCaptionsSize: this.customConfig.cache.captions.size,
|
|
||||||
signupEnabled: this.customConfig.signup.enabled,
|
|
||||||
signupLimit: this.customConfig.signup.limit,
|
|
||||||
signupRequiresEmailVerification: this.customConfig.signup.requiresEmailVerification,
|
|
||||||
adminEmail: this.customConfig.admin.email,
|
|
||||||
userVideoQuota: this.customConfig.user.videoQuota,
|
|
||||||
userVideoQuotaDaily: this.customConfig.user.videoQuotaDaily,
|
|
||||||
transcodingThreads: this.customConfig.transcoding.threads,
|
|
||||||
transcodingEnabled: this.customConfig.transcoding.enabled,
|
|
||||||
transcodingAllowAdditionalExtensions: this.customConfig.transcoding.allowAdditionalExtensions,
|
|
||||||
customizationJavascript: this.customConfig.instance.customizations.javascript,
|
|
||||||
customizationCSS: this.customConfig.instance.customizations.css,
|
|
||||||
importVideosHttpEnabled: this.customConfig.import.videos.http.enabled,
|
|
||||||
importVideosTorrentEnabled: this.customConfig.import.videos.torrent.enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const resolution of this.resolutions) {
|
|
||||||
const key = this.getResolutionKey(resolution)
|
|
||||||
data[key] = this.customConfig.transcoding.resolutions[resolution]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.form.patchValue(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,9 @@ export class ServerService {
|
||||||
email: {
|
email: {
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
|
contactForm: {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
serverVersion: 'Unknown',
|
serverVersion: 'Unknown',
|
||||||
signup: {
|
signup: {
|
||||||
allowed: false,
|
allowed: false,
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { FormGroup } from '@angular/forms'
|
import { FormGroup } from '@angular/forms'
|
||||||
import { BuildFormArgument, BuildFormDefaultValues, FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
import { BuildFormArgument, BuildFormDefaultValues, FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
|
||||||
|
|
||||||
export type FormReactiveErrors = { [ id: string ]: string }
|
export type FormReactiveErrors = { [ id: string ]: string | FormReactiveErrors }
|
||||||
export type FormReactiveValidationMessages = {
|
export type FormReactiveValidationMessages = {
|
||||||
[ id: string ]: {
|
[ id: string ]: { [ name: string ]: string } | FormReactiveValidationMessages
|
||||||
[ name: string ]: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class FormReactive {
|
export abstract class FormReactive {
|
||||||
|
@ -23,29 +21,49 @@ export abstract class FormReactive {
|
||||||
this.formErrors = formErrors
|
this.formErrors = formErrors
|
||||||
this.validationMessages = validationMessages
|
this.validationMessages = validationMessages
|
||||||
|
|
||||||
this.form.valueChanges.subscribe(() => this.onValueChanged(false))
|
this.form.valueChanges.subscribe(() => this.onValueChanged(this.form, this.formErrors, this.validationMessages, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onValueChanged (forceCheck = false) {
|
protected forceCheck () {
|
||||||
for (const field in this.formErrors) {
|
return this.onValueChanged(this.form, this.formErrors, this.validationMessages, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected check () {
|
||||||
|
return this.onValueChanged(this.form, this.formErrors, this.validationMessages, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private onValueChanged (
|
||||||
|
form: FormGroup,
|
||||||
|
formErrors: FormReactiveErrors,
|
||||||
|
validationMessages: FormReactiveValidationMessages,
|
||||||
|
forceCheck = false
|
||||||
|
) {
|
||||||
|
for (const field of Object.keys(formErrors)) {
|
||||||
|
if (formErrors[field] && typeof formErrors[field] === 'object') {
|
||||||
|
this.onValueChanged(
|
||||||
|
form.controls[field] as FormGroup,
|
||||||
|
formErrors[field] as FormReactiveErrors,
|
||||||
|
validationMessages[field] as FormReactiveValidationMessages,
|
||||||
|
forceCheck
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// clear previous error message (if any)
|
// clear previous error message (if any)
|
||||||
this.formErrors[ field ] = ''
|
formErrors[ field ] = ''
|
||||||
const control = this.form.get(field)
|
const control = form.get(field)
|
||||||
|
|
||||||
if (control.dirty) this.formChanged = true
|
if (control.dirty) this.formChanged = true
|
||||||
|
|
||||||
// Don't care if dirty on force check
|
// Don't care if dirty on force check
|
||||||
const isDirty = control.dirty || forceCheck === true
|
const isDirty = control.dirty || forceCheck === true
|
||||||
if (control && isDirty && !control.valid) {
|
if (control && isDirty && !control.valid) {
|
||||||
const messages = this.validationMessages[ field ]
|
const messages = validationMessages[ field ]
|
||||||
for (const key in control.errors) {
|
for (const key in control.errors) {
|
||||||
this.formErrors[ field ] += messages[ key ] + ' '
|
formErrors[ field ] += messages[ key ] + ' '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected forceCheck () {
|
|
||||||
return this.onValueChanged(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ export type BuildFormValidator = {
|
||||||
MESSAGES: { [ name: string ]: string }
|
MESSAGES: { [ name: string ]: string }
|
||||||
}
|
}
|
||||||
export type BuildFormArgument = {
|
export type BuildFormArgument = {
|
||||||
[ id: string ]: BuildFormValidator
|
[ id: string ]: BuildFormValidator | BuildFormArgument
|
||||||
}
|
}
|
||||||
export type BuildFormDefaultValues = {
|
export type BuildFormDefaultValues = {
|
||||||
[ name: string ]: string | string[]
|
[ name: string ]: string | string[] | BuildFormDefaultValues
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -29,7 +29,16 @@ export class FormValidatorService {
|
||||||
formErrors[name] = ''
|
formErrors[name] = ''
|
||||||
|
|
||||||
const field = obj[name]
|
const field = obj[name]
|
||||||
if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES
|
if (this.isRecursiveField(field)) {
|
||||||
|
const result = this.buildForm(field as BuildFormArgument, defaultValues[name] as BuildFormDefaultValues)
|
||||||
|
group[name] = result.form
|
||||||
|
formErrors[name] = result.formErrors
|
||||||
|
validationMessages[name] = result.validationMessages
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
|
||||||
|
|
||||||
const defaultValue = defaultValues[name] || ''
|
const defaultValue = defaultValues[name] || ''
|
||||||
|
|
||||||
|
@ -52,13 +61,27 @@ export class FormValidatorService {
|
||||||
formErrors[name] = ''
|
formErrors[name] = ''
|
||||||
|
|
||||||
const field = obj[name]
|
const field = obj[name]
|
||||||
if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES
|
if (this.isRecursiveField(field)) {
|
||||||
|
this.updateForm(
|
||||||
|
form[name],
|
||||||
|
formErrors[name] as FormReactiveErrors,
|
||||||
|
validationMessages[name] as FormReactiveValidationMessages,
|
||||||
|
obj[name] as BuildFormArgument,
|
||||||
|
defaultValues[name] as BuildFormDefaultValues
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
|
||||||
|
|
||||||
const defaultValue = defaultValues[name] || ''
|
const defaultValue = defaultValues[name] || ''
|
||||||
|
|
||||||
if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS))
|
if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS as ValidatorFn[]))
|
||||||
else form.addControl(name, new FormControl(defaultValue))
|
else form.addControl(name, new FormControl(defaultValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isRecursiveField (field: any) {
|
||||||
|
return field && typeof field === 'object' && !field.MESSAGES && !field.VALIDATORS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ {
|
/deep/ {
|
||||||
.popover-help.popover {
|
.help-popover {
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
|
|
||||||
.popover-body {
|
.popover-body {
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class RemoteSubscribeComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
onValidKey () {
|
onValidKey () {
|
||||||
this.onValueChanged()
|
this.check()
|
||||||
if (!this.form.valid) return
|
if (!this.form.valid) return
|
||||||
|
|
||||||
this.formValidated()
|
this.formValidated()
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
onValidKey () {
|
onValidKey () {
|
||||||
this.onValueChanged()
|
this.check()
|
||||||
if (!this.form.valid) return
|
if (!this.form.valid) return
|
||||||
|
|
||||||
this.formValidated()
|
this.formValidated()
|
||||||
|
|
Loading…
Reference in New Issue