diff options
Diffstat (limited to 'client/src/app/+admin')
6 files changed, 271 insertions, 272 deletions
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts index 8d50b8715..d7ae2f7f0 100644 --- a/client/src/app/+admin/admin.module.ts +++ b/client/src/app/+admin/admin.module.ts | |||
@@ -1,7 +1,6 @@ | |||
1 | import { NgModule } from '@angular/core' | 1 | import { NgModule } from '@angular/core' |
2 | import { ConfigComponent, EditCustomConfigComponent } from '@app/+admin/config' | 2 | import { ConfigComponent, EditCustomConfigComponent } from '@app/+admin/config' |
3 | import { ConfigService } from '@app/+admin/config/shared/config.service' | 3 | import { ConfigService } from '@app/+admin/config/shared/config.service' |
4 | import { TabsModule } from 'ngx-bootstrap/tabs' | ||
5 | import { TableModule } from 'primeng/table' | 4 | import { TableModule } from 'primeng/table' |
6 | import { SharedModule } from '../shared' | 5 | import { SharedModule } from '../shared' |
7 | import { AdminRoutingModule } from './admin-routing.module' | 6 | import { AdminRoutingModule } from './admin-routing.module' |
@@ -18,7 +17,6 @@ import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-bl | |||
18 | @NgModule({ | 17 | @NgModule({ |
19 | imports: [ | 18 | imports: [ |
20 | AdminRoutingModule, | 19 | AdminRoutingModule, |
21 | TabsModule.forRoot(), | ||
22 | TableModule, | 20 | TableModule, |
23 | SharedModule | 21 | SharedModule |
24 | ], | 22 | ], |
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html index 0a032df12..49b89cef4 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html | |||
@@ -1,290 +1,295 @@ | |||
1 | <form role="form" [formGroup]="form"> | 1 | <form role="form" [formGroup]="form"> |
2 | 2 | ||
3 | <tabset class="root-tabset bootstrap"> | 3 | <ngb-tabset class="root-tabset bootstrap"> |
4 | 4 | ||
5 | <tab i18n-heading heading="Basic configuration"> | 5 | <ngb-tab i18n-title title="Basic configuration"> |
6 | <ng-template ngbTabContent> | ||
6 | 7 | ||
7 | <div i18n class="inner-form-title">Instance</div> | 8 | <div i18n class="inner-form-title">Instance</div> |
8 | 9 | ||
9 | <div class="form-group"> | 10 | <div class="form-group"> |
10 | <label i18n for="instanceName">Name</label> | 11 | <label i18n for="instanceName">Name</label> |
11 | <input | 12 | <input |
12 | type="text" id="instanceName" | 13 | type="text" id="instanceName" |
13 | formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }" | 14 | formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }" |
14 | > | 15 | > |
15 | <div *ngIf="formErrors.instanceName" class="form-error"> | 16 | <div *ngIf="formErrors.instanceName" class="form-error"> |
16 | {{ formErrors.instanceName }} | 17 | {{ formErrors.instanceName }} |
17 | </div> | 18 | </div> |
18 | </div> | ||
19 | |||
20 | <div class="form-group"> | ||
21 | <label i18n for="instanceShortDescription">Short description</label> | ||
22 | <textarea | ||
23 | id="instanceShortDescription" formControlName="instanceShortDescription" | ||
24 | [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }" | ||
25 | ></textarea> | ||
26 | <div *ngIf="formErrors.instanceShortDescription" class="form-error"> | ||
27 | {{ formErrors.instanceShortDescription }} | ||
28 | </div> | ||
29 | </div> | ||
30 | |||
31 | <div class="form-group"> | ||
32 | <label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help> | ||
33 | <my-markdown-textarea | ||
34 | id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true" | ||
35 | [classes]="{ 'input-error': formErrors['instanceDescription'] }" | ||
36 | ></my-markdown-textarea> | ||
37 | <div *ngIf="formErrors.instanceDescription" class="form-error"> | ||
38 | {{ formErrors.instanceDescription }} | ||
39 | </div> | ||
40 | </div> | ||
41 | |||
42 | <div class="form-group"> | ||
43 | <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help> | ||
44 | <my-markdown-textarea | ||
45 | id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true" | ||
46 | [ngClass]="{ 'input-error': formErrors['instanceTerms'] }" | ||
47 | ></my-markdown-textarea> | ||
48 | <div *ngIf="formErrors.instanceTerms" class="form-error"> | ||
49 | {{ formErrors.instanceTerms }} | ||
50 | </div> | ||
51 | </div> | ||
52 | |||
53 | <div class="form-group"> | ||
54 | <label i18n for="instanceDefaultClientRoute">Default client route</label> | ||
55 | <div class="peertube-select-container"> | ||
56 | <select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute"> | ||
57 | <option i18n value="/videos/trending">Videos Trending</option> | ||
58 | <option i18n value="/videos/recently-added">Videos Recently Added</option> | ||
59 | <option i18n value="/videos/local">Local videos</option> | ||
60 | </select> | ||
61 | </div> | ||
62 | <div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error"> | ||
63 | {{ formErrors.instanceDefaultClientRoute }} | ||
64 | </div> | ||
65 | </div> | ||
66 | |||
67 | <div class="form-group"> | ||
68 | <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label> | ||
69 | <my-help | ||
70 | helpType="custom" i18n-customHtml | ||
71 | customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video." | ||
72 | ></my-help> | ||
73 | |||
74 | <div class="peertube-select-container"> | ||
75 | <select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy"> | ||
76 | <option i18n value="do_not_list">Do not list</option> | ||
77 | <option i18n value="blur">Blur thumbnails</option> | ||
78 | <option i18n value="display">Display</option> | ||
79 | </select> | ||
80 | </div> | 19 | </div> |
81 | <div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error"> | 20 | |
82 | {{ formErrors.instanceDefaultNSFWPolicy }} | 21 | <div class="form-group"> |
22 | <label i18n for="instanceShortDescription">Short description</label> | ||
23 | <textarea | ||
24 | id="instanceShortDescription" formControlName="instanceShortDescription" | ||
25 | [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }" | ||
26 | ></textarea> | ||
27 | <div *ngIf="formErrors.instanceShortDescription" class="form-error"> | ||
28 | {{ formErrors.instanceShortDescription }} | ||
29 | </div> | ||
83 | </div> | 30 | </div> |
84 | </div> | 31 | |
85 | 32 | <div class="form-group"> | |
86 | <div i18n class="inner-form-title">Signup</div> | 33 | <label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help> |
87 | 34 | <my-markdown-textarea | |
88 | <my-peertube-checkbox | 35 | id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true" |
89 | inputName="signupEnabled" formControlName="signupEnabled" | 36 | [classes]="{ 'input-error': formErrors['instanceDescription'] }" |
90 | i18n-labelText labelText="Signup enabled" | 37 | ></my-markdown-textarea> |
91 | ></my-peertube-checkbox> | 38 | <div *ngIf="formErrors.instanceDescription" class="form-error"> |
92 | 39 | {{ formErrors.instanceDescription }} | |
93 | <div *ngIf="isSignupEnabled()" class="form-group"> | 40 | </div> |
94 | <label i18n for="signupLimit">Signup limit</label> | ||
95 | <input | ||
96 | type="text" id="signupLimit" | ||
97 | formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }" | ||
98 | > | ||
99 | <div *ngIf="formErrors.signupLimit" class="form-error"> | ||
100 | {{ formErrors.signupLimit }} | ||
101 | </div> | 41 | </div> |
102 | </div> | 42 | |
103 | 43 | <div class="form-group"> | |
104 | <div i18n class="inner-form-title">Import</div> | 44 | <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help> |
105 | 45 | <my-markdown-textarea | |
106 | <my-peertube-checkbox | 46 | id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true" |
107 | inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled" | 47 | [ngClass]="{ 'input-error': formErrors['instanceTerms'] }" |
108 | i18n-labelText labelText="Video import with HTTP enabled" | 48 | ></my-markdown-textarea> |
109 | ></my-peertube-checkbox> | 49 | <div *ngIf="formErrors.instanceTerms" class="form-error"> |
110 | 50 | {{ formErrors.instanceTerms }} | |
111 | <my-peertube-checkbox | 51 | </div> |
112 | inputName="importVideosTorrentEnabled" formControlName="importVideosTorrentEnabled" | ||
113 | i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled" | ||
114 | ></my-peertube-checkbox> | ||
115 | |||
116 | <div i18n class="inner-form-title">Administrator</div> | ||
117 | |||
118 | <div class="form-group"> | ||
119 | <label i18n for="adminEmail">Admin email</label> | ||
120 | <input | ||
121 | type="text" id="adminEmail" | ||
122 | formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }" | ||
123 | > | ||
124 | <div *ngIf="formErrors.adminEmail" class="form-error"> | ||
125 | {{ formErrors.adminEmail }} | ||
126 | </div> | 52 | </div> |
127 | </div> | 53 | |
128 | 54 | <div class="form-group"> | |
129 | <div i18n class="inner-form-title">Users</div> | 55 | <label i18n for="instanceDefaultClientRoute">Default client route</label> |
130 | 56 | <div class="peertube-select-container"> | |
131 | <div class="form-group"> | 57 | <select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute"> |
132 | <label i18n for="userVideoQuota">User default video quota</label> | 58 | <option i18n value="/videos/trending">Videos Trending</option> |
133 | <div class="peertube-select-container"> | 59 | <option i18n value="/videos/recently-added">Videos Recently Added</option> |
134 | <select id="userVideoQuota" formControlName="userVideoQuota"> | 60 | <option i18n value="/videos/local">Local videos</option> |
135 | <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value"> | 61 | </select> |
136 | {{ videoQuotaOption.label }} | 62 | </div> |
137 | </option> | 63 | <div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error"> |
138 | </select> | 64 | {{ formErrors.instanceDefaultClientRoute }} |
65 | </div> | ||
139 | </div> | 66 | </div> |
140 | <div *ngIf="formErrors.userVideoQuota" class="form-error"> | 67 | |
141 | {{ formErrors.userVideoQuota }} | 68 | <div class="form-group"> |
69 | <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label> | ||
70 | <my-help | ||
71 | helpType="custom" i18n-customHtml | ||
72 | customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video." | ||
73 | ></my-help> | ||
74 | |||
75 | <div class="peertube-select-container"> | ||
76 | <select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy"> | ||
77 | <option i18n value="do_not_list">Do not list</option> | ||
78 | <option i18n value="blur">Blur thumbnails</option> | ||
79 | <option i18n value="display">Display</option> | ||
80 | </select> | ||
81 | </div> | ||
82 | <div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error"> | ||
83 | {{ formErrors.instanceDefaultNSFWPolicy }} | ||
84 | </div> | ||
142 | </div> | 85 | </div> |
143 | </div> | 86 | |
144 | </tab> | 87 | <div i18n class="inner-form-title">Signup</div> |
145 | 88 | ||
146 | <tab i18n-heading heading="Services"> | 89 | <my-peertube-checkbox |
147 | 90 | inputName="signupEnabled" formControlName="signupEnabled" | |
148 | <div i18n class="inner-form-title">Twitter</div> | 91 | i18n-labelText labelText="Signup enabled" |
149 | 92 | ></my-peertube-checkbox> | |
150 | <div class="form-group"> | 93 | |
151 | <label i18n for="signupLimit">Your Twitter username</label> | 94 | <div *ngIf="isSignupEnabled()" class="form-group"> |
152 | <my-help | 95 | <label i18n for="signupLimit">Signup limit</label> |
153 | helpType="custom" i18n-customHtml | 96 | <input |
154 | customHtml="Indicates the Twitter account for the website or platform on which the content was published." | 97 | type="text" id="signupLimit" |
155 | ></my-help> | 98 | formControlName="signupLimit" [ngClass]="{ 'input-error': formErrors['signupLimit'] }" |
156 | <input | 99 | > |
157 | type="text" id="servicesTwitterUsername" | 100 | <div *ngIf="formErrors.signupLimit" class="form-error"> |
158 | formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }" | 101 | {{ formErrors.signupLimit }} |
159 | > | 102 | </div> |
160 | <div *ngIf="formErrors.servicesTwitterUsername" class="form-error"> | ||
161 | {{ formErrors.servicesTwitterUsername }} | ||
162 | </div> | 103 | </div> |
163 | </div> | ||
164 | 104 | ||
165 | <my-peertube-checkbox | 105 | <div i18n class="inner-form-title">Import</div> |
166 | inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted" | 106 | |
167 | i18n-labelText labelText="Instance whitelisted by Twitter" | 107 | <my-peertube-checkbox |
168 | 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 /> | 108 | inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled" |
169 | If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br /> | 109 | i18n-labelText labelText="Video import with HTTP enabled" |
170 | 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." | 110 | ></my-peertube-checkbox> |
171 | ></my-peertube-checkbox> | ||
172 | </tab> | ||
173 | 111 | ||
174 | <tab i18n-heading heading="Advanced configuration"> | 112 | <my-peertube-checkbox |
113 | inputName="importVideosTorrentEnabled" formControlName="importVideosTorrentEnabled" | ||
114 | i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled" | ||
115 | ></my-peertube-checkbox> | ||
175 | 116 | ||
176 | <div i18n class="inner-form-title">Transcoding</div> | 117 | <div i18n class="inner-form-title">Administrator</div> |
177 | 118 | ||
178 | <my-peertube-checkbox | 119 | <div class="form-group"> |
179 | inputName="transcodingEnabled" formControlName="transcodingEnabled" | 120 | <label i18n for="adminEmail">Admin email</label> |
180 | i18n-labelText labelText="Transcoding enabled" | 121 | <input |
181 | i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!" | 122 | type="text" id="adminEmail" |
182 | ></my-peertube-checkbox> | 123 | formControlName="adminEmail" [ngClass]="{ 'input-error': formErrors['adminEmail'] }" |
124 | > | ||
125 | <div *ngIf="formErrors.adminEmail" class="form-error"> | ||
126 | {{ formErrors.adminEmail }} | ||
127 | </div> | ||
128 | </div> | ||
183 | 129 | ||
184 | <ng-template [ngIf]="isTranscodingEnabled()"> | 130 | <div i18n class="inner-form-title">Users</div> |
185 | 131 | ||
186 | <div class="form-group"> | 132 | <div class="form-group"> |
187 | <label i18n for="transcodingThreads">Transcoding threads</label> | 133 | <label i18n for="userVideoQuota">User default video quota</label> |
188 | <div class="peertube-select-container"> | 134 | <div class="peertube-select-container"> |
189 | <select id="transcodingThreads" formControlName="transcodingThreads"> | 135 | <select id="userVideoQuota" formControlName="userVideoQuota"> |
190 | <option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value"> | 136 | <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value"> |
191 | {{ transcodingThreadOption.label }} | 137 | {{ videoQuotaOption.label }} |
192 | </option> | 138 | </option> |
193 | </select> | 139 | </select> |
194 | </div> | 140 | </div> |
195 | <div *ngIf="formErrors.transcodingThreads" class="form-error"> | 141 | <div *ngIf="formErrors.userVideoQuota" class="form-error"> |
196 | {{ formErrors.transcodingThreads }} | 142 | {{ formErrors.userVideoQuota }} |
197 | </div> | 143 | </div> |
198 | </div> | 144 | </div> |
145 | </ng-template> | ||
146 | </ngb-tab> | ||
199 | 147 | ||
200 | <div class="form-group" *ngFor="let resolution of resolutions"> | 148 | <ngb-tab i18n-title title="Services"> |
201 | <my-peertube-checkbox | 149 | <ng-template ngbTabContent> |
202 | [inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)" | 150 | <div i18n class="inner-form-title">Twitter</div> |
203 | i18n-labelText labelText="Resolution {{resolution}} enabled" | ||
204 | ></my-peertube-checkbox> | ||
205 | 151 | ||
152 | <div class="form-group"> | ||
153 | <label i18n for="signupLimit">Your Twitter username</label> | ||
154 | <my-help | ||
155 | helpType="custom" i18n-customHtml | ||
156 | customHtml="Indicates the Twitter account for the website or platform on which the content was published." | ||
157 | ></my-help> | ||
158 | <input | ||
159 | type="text" id="servicesTwitterUsername" | ||
160 | formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }" | ||
161 | > | ||
162 | <div *ngIf="formErrors.servicesTwitterUsername" class="form-error"> | ||
163 | {{ formErrors.servicesTwitterUsername }} | ||
164 | </div> | ||
206 | </div> | 165 | </div> |
207 | </ng-template> | ||
208 | 166 | ||
209 | <div i18n class="inner-form-title"> | 167 | <my-peertube-checkbox |
210 | Cache | 168 | inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted" |
211 | 169 | i18n-labelText labelText="Instance whitelisted by Twitter" | |
212 | <my-help | 170 | 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 /> |
213 | helpType="custom" i18n-customHtml | 171 | If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br /> |
214 | customHtml="Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them." | 172 | 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." |
215 | ></my-help> | 173 | ></my-peertube-checkbox> |
216 | </div> | 174 | </ng-template> |
217 | 175 | </ngb-tab> | |
218 | <div class="form-group"> | 176 | |
219 | <label i18n for="cachePreviewsSize">Previews cache size</label> | 177 | <ngb-tab i18n-title title="Advanced configuration"> |
220 | <input | 178 | <ng-template ngbTabContent> |
221 | type="text" id="cachePreviewsSize" | 179 | |
222 | formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }" | 180 | <div i18n class="inner-form-title">Transcoding</div> |
223 | > | 181 | |
224 | <div *ngIf="formErrors.cachePreviewsSize" class="form-error"> | 182 | <my-peertube-checkbox |
225 | {{ formErrors.cachePreviewsSize }} | 183 | inputName="transcodingEnabled" formControlName="transcodingEnabled" |
184 | i18n-labelText labelText="Transcoding enabled" | ||
185 | i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!" | ||
186 | ></my-peertube-checkbox> | ||
187 | |||
188 | <ng-template [ngIf]="isTranscodingEnabled()"> | ||
189 | |||
190 | <div class="form-group"> | ||
191 | <label i18n for="transcodingThreads">Transcoding threads</label> | ||
192 | <div class="peertube-select-container"> | ||
193 | <select id="transcodingThreads" formControlName="transcodingThreads"> | ||
194 | <option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value"> | ||
195 | {{ transcodingThreadOption.label }} | ||
196 | </option> | ||
197 | </select> | ||
198 | </div> | ||
199 | <div *ngIf="formErrors.transcodingThreads" class="form-error"> | ||
200 | {{ formErrors.transcodingThreads }} | ||
201 | </div> | ||
202 | </div> | ||
203 | |||
204 | <div class="form-group" *ngFor="let resolution of resolutions"> | ||
205 | <my-peertube-checkbox | ||
206 | [inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)" | ||
207 | i18n-labelText labelText="Resolution {{resolution}} enabled" | ||
208 | ></my-peertube-checkbox> | ||
209 | |||
210 | </div> | ||
211 | </ng-template> | ||
212 | |||
213 | <div i18n class="inner-form-title"> | ||
214 | Cache | ||
215 | |||
216 | <my-help | ||
217 | helpType="custom" i18n-customHtml | ||
218 | customHtml="Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them." | ||
219 | ></my-help> | ||
226 | </div> | 220 | </div> |
227 | </div> | 221 | |
228 | 222 | <div class="form-group"> | |
229 | <div class="form-group"> | 223 | <label i18n for="cachePreviewsSize">Previews cache size</label> |
230 | <label i18n for="cachePreviewsSize">Video captions cache size</label> | 224 | <input |
231 | <input | 225 | type="text" id="cachePreviewsSize" |
232 | type="text" id="cacheCaptionsSize" | 226 | formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }" |
233 | formControlName="cacheCaptionsSize" [ngClass]="{ 'input-error': formErrors['cacheCaptionsSize'] }" | 227 | > |
234 | > | 228 | <div *ngIf="formErrors.cachePreviewsSize" class="form-error"> |
235 | <div *ngIf="formErrors.cacheCaptionsSize" class="form-error"> | 229 | {{ formErrors.cachePreviewsSize }} |
236 | {{ formErrors.cacheCaptionsSize }} | 230 | </div> |
237 | </div> | 231 | </div> |
238 | </div> | 232 | |
239 | 233 | <div class="form-group"> | |
240 | <div i18n class="inner-form-title">Customizations</div> | 234 | <label i18n for="cachePreviewsSize">Video captions cache size</label> |
241 | 235 | <input | |
242 | <div class="form-group"> | 236 | type="text" id="cacheCaptionsSize" |
243 | <label i18n for="customizationJavascript">JavaScript</label> | 237 | formControlName="cacheCaptionsSize" [ngClass]="{ 'input-error': formErrors['cacheCaptionsSize'] }" |
244 | <my-help | 238 | > |
245 | helpType="custom" i18n-customHtml | 239 | <div *ngIf="formErrors.cacheCaptionsSize" class="form-error"> |
246 | customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>" | 240 | {{ formErrors.cacheCaptionsSize }} |
247 | ></my-help> | 241 | </div> |
248 | <textarea | ||
249 | id="customizationJavascript" formControlName="customizationJavascript" | ||
250 | [ngClass]="{ 'input-error': formErrors['customizationJavascript'] }" | ||
251 | ></textarea> | ||
252 | <div *ngIf="formErrors.customizationJavascript" class="form-error"> | ||
253 | {{ formErrors.customizationJavascript }} | ||
254 | </div> | 242 | </div> |
255 | </div> | 243 | |
256 | 244 | <div i18n class="inner-form-title">Customizations</div> | |
257 | <div class="form-group"> | 245 | |
258 | <label for="customizationCSS">CSS</label> | 246 | <div class="form-group"> |
259 | <my-help | 247 | <label i18n for="customizationJavascript">JavaScript</label> |
260 | helpType="custom" | 248 | <my-help |
261 | i18n-customHtml | 249 | helpType="custom" i18n-customHtml |
262 | customHtml=" | 250 | customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>" |
263 | Write directly CSS code. Example:<br /> | 251 | ></my-help> |
264 | <pre> | 252 | <textarea |
265 | body {{ '{' }} | 253 | id="customizationJavascript" formControlName="customizationJavascript" |
266 | background-color: red; | 254 | [ngClass]="{ 'input-error': formErrors['customizationJavascript'] }" |
267 | {{ '}' }} | 255 | ></textarea> |
268 | </pre> | 256 | <div *ngIf="formErrors.customizationJavascript" class="form-error"> |
269 | 257 | {{ formErrors.customizationJavascript }} | |
270 | Prepend with <em>#custom-css</em> to override styles. Example: | 258 | </div> |
271 | <pre> | ||
272 | #custom-css .logged-in-email {{ '{' }} | ||
273 | color: red; | ||
274 | {{ '}' }} | ||
275 | </pre> | ||
276 | " | ||
277 | ></my-help> | ||
278 | <textarea | ||
279 | id="customizationCSS" formControlName="customizationCSS" | ||
280 | [ngClass]="{ 'input-error': formErrors['customizationCSS'] }" | ||
281 | ></textarea> | ||
282 | <div *ngIf="formErrors.customizationCSS" class="form-error"> | ||
283 | {{ formErrors.customizationCSS }} | ||
284 | </div> | 259 | </div> |
285 | </div> | 260 | |
286 | </tab> | 261 | <div class="form-group"> |
287 | </tabset> | 262 | <label for="customizationCSS">CSS</label> |
263 | <my-help | ||
264 | helpType="custom" | ||
265 | i18n-customHtml | ||
266 | customHtml=" | ||
267 | Write directly CSS code. Example:<br /> | ||
268 | <pre> | ||
269 | body {{ '{' }} | ||
270 | background-color: red; | ||
271 | {{ '}' }} | ||
272 | </pre> | ||
273 | |||
274 | Prepend with <em>#custom-css</em> to override styles. Example: | ||
275 | <pre> | ||
276 | #custom-css .logged-in-email {{ '{' }} | ||
277 | color: red; | ||
278 | {{ '}' }} | ||
279 | </pre> | ||
280 | " | ||
281 | ></my-help> | ||
282 | <textarea | ||
283 | id="customizationCSS" formControlName="customizationCSS" | ||
284 | [ngClass]="{ 'input-error': formErrors['customizationCSS'] }" | ||
285 | ></textarea> | ||
286 | <div *ngIf="formErrors.customizationCSS" class="form-error"> | ||
287 | {{ formErrors.customizationCSS }} | ||
288 | </div> | ||
289 | </div> | ||
290 | </ng-template> | ||
291 | </ngb-tab> | ||
292 | </ngb-tabset> | ||
288 | 293 | ||
289 | <input (click)="formValidated()" type="submit" i18n-value value="Update configuration" [disabled]="!form.valid"> | 294 | <input (click)="formValidated()" type="submit" i18n-value value="Update configuration" [disabled]="!form.valid"> |
290 | <span class="form-error" i18n *ngIf="!form.valid">It seems the configuration is invalid. Please search potential errors in the different tabs.</span> | 295 | <span class="form-error" i18n *ngIf="!form.valid">It seems the configuration is invalid. Please search potential errors in the different tabs.</span> |
diff --git a/client/src/app/+admin/follows/following-add/following-add.component.html b/client/src/app/+admin/follows/following-add/following-add.component.html index 72635048c..e08decb3f 100644 --- a/client/src/app/+admin/follows/following-add/following-add.component.html +++ b/client/src/app/+admin/follows/following-add/following-add.component.html | |||
@@ -18,5 +18,5 @@ | |||
18 | It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers. | 18 | It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers. |
19 | </div> | 19 | </div> |
20 | 20 | ||
21 | <input type="submit" i18n-value value="Add following" [disabled]="hostsError || !hostsString" class="btn btn-default"> | 21 | <input type="submit" i18n-value value="Add following" [disabled]="hostsError || !hostsString" class="btn btn-secondary"> |
22 | </form> | 22 | </form> |
diff --git a/client/src/app/+admin/follows/follows.component.html b/client/src/app/+admin/follows/follows.component.html index a8258bf70..8eabb3392 100644 --- a/client/src/app/+admin/follows/follows.component.html +++ b/client/src/app/+admin/follows/follows.component.html | |||
@@ -1,13 +1,15 @@ | |||
1 | <div class="admin-sub-header"> | 1 | <div class="admin-sub-header"> |
2 | <div i18n class="form-sub-title">Manage follows</div> | 2 | <div i18n class="form-sub-title">Manage follows</div> |
3 | 3 | ||
4 | <tabset #followsMenuTabs> | 4 | <ngb-tabset #followsMenuTabs type="pills"> |
5 | <tab *ngFor="let link of links"> | 5 | |
6 | <ng-template tabHeading> | 6 | <ngb-tab *ngFor="let link of links"> |
7 | <ng-template ngbTabTitle> | ||
7 | <a class="tab-link" [routerLink]="link.path">{{ link.title }}</a> | 8 | <a class="tab-link" [routerLink]="link.path">{{ link.title }}</a> |
8 | </ng-template> | 9 | </ng-template> |
9 | </tab> | 10 | </ngb-tab> |
10 | </tabset> | 11 | |
12 | </ngb-tabset> | ||
11 | </div> | 13 | </div> |
12 | 14 | ||
13 | <router-outlet></router-outlet> | 15 | <router-outlet></router-outlet> |
diff --git a/client/src/app/+admin/follows/follows.component.scss b/client/src/app/+admin/follows/follows.component.scss index 08b3737f8..766d7853b 100644 --- a/client/src/app/+admin/follows/follows.component.scss +++ b/client/src/app/+admin/follows/follows.component.scss | |||
@@ -2,9 +2,3 @@ | |||
2 | flex-grow: 0; | 2 | flex-grow: 0; |
3 | margin-right: 30px; | 3 | margin-right: 30px; |
4 | } | 4 | } |
5 | |||
6 | /deep/ .tab-content { | ||
7 | height: 0; | ||
8 | min-height: 0; | ||
9 | padding: 0; | ||
10 | } | ||
diff --git a/client/src/app/+admin/follows/follows.component.ts b/client/src/app/+admin/follows/follows.component.ts index f7af9826c..b6f7715b3 100644 --- a/client/src/app/+admin/follows/follows.component.ts +++ b/client/src/app/+admin/follows/follows.component.ts | |||
@@ -1,14 +1,14 @@ | |||
1 | import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core' | 1 | import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core' |
2 | import { NavigationEnd, Router } from '@angular/router' | 2 | import { NavigationEnd, Router } from '@angular/router' |
3 | import { TabsetComponent } from 'ngx-bootstrap/tabs' | ||
4 | import { I18n } from '@ngx-translate/i18n-polyfill' | 3 | import { I18n } from '@ngx-translate/i18n-polyfill' |
4 | import { NgbTabset } from '@ng-bootstrap/ng-bootstrap' | ||
5 | 5 | ||
6 | @Component({ | 6 | @Component({ |
7 | templateUrl: './follows.component.html', | 7 | templateUrl: './follows.component.html', |
8 | styleUrls: [ './follows.component.scss' ] | 8 | styleUrls: [ './follows.component.scss' ] |
9 | }) | 9 | }) |
10 | export class FollowsComponent implements OnInit, AfterViewInit { | 10 | export class FollowsComponent implements OnInit, AfterViewInit { |
11 | @ViewChild('followsMenuTabs') followsMenuTabs: TabsetComponent | 11 | @ViewChild('followsMenuTabs') followsMenuTabs: NgbTabset |
12 | 12 | ||
13 | links: { path: string, title: string }[] = [] | 13 | links: { path: string, title: string }[] = [] |
14 | 14 | ||
@@ -53,8 +53,8 @@ export class FollowsComponent implements OnInit, AfterViewInit { | |||
53 | for (let i = 0; i < this.links.length; i++) { | 53 | for (let i = 0; i < this.links.length; i++) { |
54 | const path = this.links[i].path | 54 | const path = this.links[i].path |
55 | 55 | ||
56 | if (url.endsWith(path) === true && this.followsMenuTabs.tabs[i]) { | 56 | if (url.endsWith(path) === true) { |
57 | this.followsMenuTabs.tabs[i].active = true | 57 | this.followsMenuTabs.select(path) |
58 | return | 58 | return |
59 | } | 59 | } |
60 | } | 60 | } |