Migrate to bootstrap 4 and ng-bootstrap
authorChocobozzz <me@florianbigard.com>
Thu, 9 Aug 2018 12:55:06 +0000 (14:55 +0200)
committerChocobozzz <me@florianbigard.com>
Thu, 9 Aug 2018 12:55:06 +0000 (14:55 +0200)
44 files changed:
client/package.json
client/src/app/+admin/admin.module.ts
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
client/src/app/+admin/follows/following-add/following-add.component.html
client/src/app/+admin/follows/follows.component.html
client/src/app/+admin/follows/follows.component.scss
client/src/app/+admin/follows/follows.component.ts
client/src/app/core/confirm/confirm.component.html
client/src/app/core/confirm/confirm.component.ts
client/src/app/core/core.module.ts
client/src/app/login/login.component.html
client/src/app/login/login.component.ts
client/src/app/menu/language-chooser.component.html
client/src/app/menu/language-chooser.component.scss
client/src/app/menu/language-chooser.component.ts
client/src/app/menu/menu.component.html
client/src/app/menu/menu.component.scss
client/src/app/search/search.component.html
client/src/app/search/search.module.ts
client/src/app/shared/forms/markdown-textarea.component.html
client/src/app/shared/misc/help.component.html
client/src/app/shared/shared.module.ts
client/src/app/shared/video/video-feed.component.html
client/src/app/shared/video/video-feed.component.scss
client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html
client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.ts
client/src/app/videos/+video-edit/shared/video-edit.component.html
client/src/app/videos/+video-edit/shared/video-edit.component.scss
client/src/app/videos/+video-edit/shared/video-edit.module.ts
client/src/app/videos/+video-watch/modal/video-download.component.html
client/src/app/videos/+video-watch/modal/video-download.component.ts
client/src/app/videos/+video-watch/modal/video-report.component.html
client/src/app/videos/+video-watch/modal/video-report.component.ts
client/src/app/videos/+video-watch/modal/video-share.component.html
client/src/app/videos/+video-watch/modal/video-share.component.scss
client/src/app/videos/+video-watch/modal/video-share.component.ts
client/src/app/videos/+video-watch/modal/video-support.component.html
client/src/app/videos/+video-watch/modal/video-support.component.ts
client/src/app/videos/+video-watch/video-watch.component.html
client/src/app/videos/+video-watch/video-watch.component.scss
client/src/app/videos/+video-watch/video-watch.module.ts
client/src/sass/application.scss
client/src/sass/include/_bootstrap.scss
client/yarn.lock

index e6b6e3b05fdb6ed2196eee37d8092b21e0c0fa72..0360502f99798921813e106864f33a30f401d05d 100644 (file)
@@ -46,6 +46,7 @@
     "@angular/service-worker": "~6.1.0",
     "@angularclass/hmr": "^2.1.3",
     "@neos21/bootstrap3-glyphicons": "^1.0.1",
+    "@ng-bootstrap/ng-bootstrap": "^2.2.2",
     "@ngx-loading-bar/core": "^2.0.0",
     "@ngx-loading-bar/http-client": "^2.0.0",
     "@ngx-loading-bar/router": "^2.0.0",
@@ -86,7 +87,6 @@
     "linkifyjs": "^2.1.5",
     "lodash-es": "^4.17.4",
     "markdown-it": "^8.4.0",
-    "ngx-bootstrap": "3.0.1",
     "ngx-chips": "1.9.3",
     "ngx-clipboard": "11.1.1",
     "ngx-pipes": "^2.1.7",
index 8d50b8715612506ed61d7590982e244069711540..d7ae2f7f0ad1aebb5e6c89de8224c9cda181cc22 100644 (file)
@@ -1,7 +1,6 @@
 import { NgModule } from '@angular/core'
 import { ConfigComponent, EditCustomConfigComponent } from '@app/+admin/config'
 import { ConfigService } from '@app/+admin/config/shared/config.service'
-import { TabsModule } from 'ngx-bootstrap/tabs'
 import { TableModule } from 'primeng/table'
 import { SharedModule } from '../shared'
 import { AdminRoutingModule } from './admin-routing.module'
@@ -18,7 +17,6 @@ import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-bl
 @NgModule({
   imports: [
     AdminRoutingModule,
-    TabsModule.forRoot(),
     TableModule,
     SharedModule
   ],
index 0a032df1269b9c0c6ea3026ad495c7839b5012a9..49b89cef474ffc3c4e6380a96a136962002a63b2 100644 (file)
 <form role="form" [formGroup]="form">
 
-  <tabset class="root-tabset bootstrap">
+  <ngb-tabset class="root-tabset bootstrap">
 
-    <tab i18n-heading heading="Basic configuration">
+    <ngb-tab i18n-title title="Basic configuration">
+      <ng-template ngbTabContent>
 
-      <div i18n class="inner-form-title">Instance</div>
+        <div i18n class="inner-form-title">Instance</div>
 
-      <div class="form-group">
-        <label i18n for="instanceName">Name</label>
-        <input
-          type="text" id="instanceName"
-          formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }"
-        >
-        <div *ngIf="formErrors.instanceName" class="form-error">
-          {{ formErrors.instanceName }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="instanceShortDescription">Short description</label>
-        <textarea
-          id="instanceShortDescription" formControlName="instanceShortDescription"
-          [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
-        ></textarea>
-        <div *ngIf="formErrors.instanceShortDescription" class="form-error">
-          {{ formErrors.instanceShortDescription }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
-        <my-markdown-textarea
-          id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true"
-          [classes]="{ 'input-error': formErrors['instanceDescription'] }"
-        ></my-markdown-textarea>
-        <div *ngIf="formErrors.instanceDescription" class="form-error">
-          {{ formErrors.instanceDescription }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
-        <my-markdown-textarea
-          id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true"
-          [ngClass]="{ 'input-error': formErrors['instanceTerms'] }"
-        ></my-markdown-textarea>
-        <div *ngIf="formErrors.instanceTerms" class="form-error">
-          {{ formErrors.instanceTerms }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="instanceDefaultClientRoute">Default client route</label>
-        <div class="peertube-select-container">
-          <select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
-            <option i18n value="/videos/trending">Videos Trending</option>
-            <option i18n value="/videos/recently-added">Videos Recently Added</option>
-            <option i18n value="/videos/local">Local videos</option>
-          </select>
-        </div>
-        <div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error">
-          {{ formErrors.instanceDefaultClientRoute }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
-        <my-help
-          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."
-        ></my-help>
-
-        <div class="peertube-select-container">
-          <select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy">
-            <option i18n value="do_not_list">Do not list</option>
-            <option i18n value="blur">Blur thumbnails</option>
-            <option i18n value="display">Display</option>
-          </select>
+        <div class="form-group">
+          <label i18n for="instanceName">Name</label>
+          <input
+            type="text" id="instanceName"
+            formControlName="instanceName" [ngClass]="{ 'input-error': formErrors['instanceName'] }"
+          >
+          <div *ngIf="formErrors.instanceName" class="form-error">
+            {{ formErrors.instanceName }}
+          </div>
         </div>
-        <div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error">
-          {{ formErrors.instanceDefaultNSFWPolicy }}
+
+        <div class="form-group">
+          <label i18n for="instanceShortDescription">Short description</label>
+          <textarea
+            id="instanceShortDescription" formControlName="instanceShortDescription"
+            [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
+          ></textarea>
+          <div *ngIf="formErrors.instanceShortDescription" class="form-error">
+            {{ formErrors.instanceShortDescription }}
+          </div>
         </div>
-      </div>
-
-      <div i18n class="inner-form-title">Signup</div>
-
-      <my-peertube-checkbox
-        inputName="signupEnabled" formControlName="signupEnabled"
-        i18n-labelText labelText="Signup enabled"
-      ></my-peertube-checkbox>
-
-      <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 class="form-group">
+          <label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
+          <my-markdown-textarea
+            id="instanceDescription" formControlName="instanceDescription" textareaWidth="500px" [previewColumn]="true"
+            [classes]="{ 'input-error': formErrors['instanceDescription'] }"
+          ></my-markdown-textarea>
+          <div *ngIf="formErrors.instanceDescription" class="form-error">
+            {{ formErrors.instanceDescription }}
+          </div>
         </div>
-      </div>
-
-      <div i18n class="inner-form-title">Import</div>
-
-      <my-peertube-checkbox
-        inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled"
-        i18n-labelText labelText="Video import with HTTP enabled"
-      ></my-peertube-checkbox>
-
-      <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 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 class="form-group">
+          <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
+          <my-markdown-textarea
+            id="instanceTerms" formControlName="instanceTerms" textareaWidth="500px" [previewColumn]="true"
+            [ngClass]="{ 'input-error': formErrors['instanceTerms'] }"
+          ></my-markdown-textarea>
+          <div *ngIf="formErrors.instanceTerms" class="form-error">
+            {{ formErrors.instanceTerms }}
+          </div>
         </div>
-      </div>
-
-      <div i18n class="inner-form-title">Users</div>
-
-      <div class="form-group">
-        <label i18n for="userVideoQuota">User default video quota</label>
-        <div class="peertube-select-container">
-          <select id="userVideoQuota" formControlName="userVideoQuota">
-            <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
-              {{ videoQuotaOption.label }}
-            </option>
-          </select>
+
+        <div class="form-group">
+          <label i18n for="instanceDefaultClientRoute">Default client route</label>
+          <div class="peertube-select-container">
+            <select id="instanceDefaultClientRoute" formControlName="instanceDefaultClientRoute">
+              <option i18n value="/videos/trending">Videos Trending</option>
+              <option i18n value="/videos/recently-added">Videos Recently Added</option>
+              <option i18n value="/videos/local">Local videos</option>
+            </select>
+          </div>
+          <div *ngIf="formErrors.instanceDefaultClientRoute" class="form-error">
+            {{ formErrors.instanceDefaultClientRoute }}
+          </div>
         </div>
-        <div *ngIf="formErrors.userVideoQuota" class="form-error">
-          {{ formErrors.userVideoQuota }}
+
+        <div class="form-group">
+          <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
+          <my-help
+            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."
+          ></my-help>
+
+          <div class="peertube-select-container">
+            <select id="instanceDefaultNSFWPolicy" formControlName="instanceDefaultNSFWPolicy">
+              <option i18n value="do_not_list">Do not list</option>
+              <option i18n value="blur">Blur thumbnails</option>
+              <option i18n value="display">Display</option>
+            </select>
+          </div>
+          <div *ngIf="formErrors.instanceDefaultNSFWPolicy" class="form-error">
+            {{ formErrors.instanceDefaultNSFWPolicy }}
+          </div>
         </div>
-      </div>
-    </tab>
-
-    <tab i18n-heading heading="Services">
-
-      <div i18n class="inner-form-title">Twitter</div>
-
-      <div class="form-group">
-        <label i18n for="signupLimit">Your Twitter username</label>
-        <my-help
-          helpType="custom" i18n-customHtml
-          customHtml="Indicates the Twitter account for the website or platform on which the content was published."
-        ></my-help>
-        <input
-          type="text" id="servicesTwitterUsername"
-          formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }"
-        >
-        <div *ngIf="formErrors.servicesTwitterUsername" class="form-error">
-          {{ formErrors.servicesTwitterUsername }}
+
+        <div i18n class="inner-form-title">Signup</div>
+
+        <my-peertube-checkbox
+          inputName="signupEnabled" formControlName="signupEnabled"
+          i18n-labelText labelText="Signup enabled"
+        ></my-peertube-checkbox>
+
+        <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>
 
-      <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>
-    </tab>
+        <div i18n class="inner-form-title">Import</div>
+
+        <my-peertube-checkbox
+          inputName="importVideosHttpEnabled" formControlName="importVideosHttpEnabled"
+          i18n-labelText labelText="Video import with HTTP enabled"
+        ></my-peertube-checkbox>
 
-    <tab i18n-heading heading="Advanced configuration">
+        <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 i18n class="inner-form-title">Transcoding</div>
+        <div i18n class="inner-form-title">Administrator</div>
 
-      <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 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>
 
-      <ng-template [ngIf]="isTranscodingEnabled()">
+        <div i18n class="inner-form-title">Users</div>
 
         <div class="form-group">
-          <label i18n for="transcodingThreads">Transcoding threads</label>
+          <label i18n for="userVideoQuota">User default video quota</label>
           <div class="peertube-select-container">
-            <select id="transcodingThreads" formControlName="transcodingThreads">
-              <option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
-                {{ transcodingThreadOption.label }}
+            <select id="userVideoQuota" formControlName="userVideoQuota">
+              <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
+                {{ videoQuotaOption.label }}
               </option>
             </select>
           </div>
-          <div *ngIf="formErrors.transcodingThreads" class="form-error">
-            {{ formErrors.transcodingThreads }}
+          <div *ngIf="formErrors.userVideoQuota" class="form-error">
+            {{ formErrors.userVideoQuota }}
           </div>
         </div>
+      </ng-template>
+    </ngb-tab>
 
-        <div class="form-group" *ngFor="let resolution of resolutions">
-          <my-peertube-checkbox
-            [inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)"
-            i18n-labelText labelText="Resolution {{resolution}} enabled"
-          ></my-peertube-checkbox>
+    <ngb-tab i18n-title title="Services">
+      <ng-template ngbTabContent>
+        <div i18n class="inner-form-title">Twitter</div>
 
+        <div class="form-group">
+          <label i18n for="signupLimit">Your Twitter username</label>
+          <my-help
+            helpType="custom" i18n-customHtml
+            customHtml="Indicates the Twitter account for the website or platform on which the content was published."
+          ></my-help>
+          <input
+            type="text" id="servicesTwitterUsername"
+            formControlName="servicesTwitterUsername" [ngClass]="{ 'input-error': formErrors['servicesTwitterUsername'] }"
+          >
+          <div *ngIf="formErrors.servicesTwitterUsername" class="form-error">
+            {{ formErrors.servicesTwitterUsername }}
+          </div>
         </div>
-      </ng-template>
 
-      <div i18n class="inner-form-title">
-        Cache
-
-        <my-help
-          helpType="custom" i18n-customHtml
-          customHtml="Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them."
-        ></my-help>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="cachePreviewsSize">Previews cache size</label>
-        <input
-          type="text" id="cachePreviewsSize"
-          formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }"
-        >
-        <div *ngIf="formErrors.cachePreviewsSize" class="form-error">
-          {{ formErrors.cachePreviewsSize }}
+        <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>
+    </ng-template>
+    </ngb-tab>
+
+    <ngb-tab i18n-title title="Advanced configuration">
+      <ng-template ngbTabContent>
+
+        <div i18n class="inner-form-title">Transcoding</div>
+
+        <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>
+
+        <ng-template [ngIf]="isTranscodingEnabled()">
+
+          <div class="form-group">
+            <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">
+            <my-peertube-checkbox
+              [inputName]="getResolutionKey(resolution)" [formControlName]="getResolutionKey(resolution)"
+              i18n-labelText labelText="Resolution {{resolution}} enabled"
+            ></my-peertube-checkbox>
+
+          </div>
+        </ng-template>
+
+        <div i18n class="inner-form-title">
+          Cache
+
+          <my-help
+            helpType="custom" i18n-customHtml
+            customHtml="Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them."
+          ></my-help>
         </div>
-      </div>
-
-      <div class="form-group">
-        <label i18n for="cachePreviewsSize">Video captions cache size</label>
-        <input
-          type="text" id="cacheCaptionsSize"
-          formControlName="cacheCaptionsSize" [ngClass]="{ 'input-error': formErrors['cacheCaptionsSize'] }"
-        >
-        <div *ngIf="formErrors.cacheCaptionsSize" class="form-error">
-          {{ formErrors.cacheCaptionsSize }}
+
+        <div class="form-group">
+          <label i18n for="cachePreviewsSize">Previews cache size</label>
+          <input
+            type="text" id="cachePreviewsSize"
+            formControlName="cachePreviewsSize" [ngClass]="{ 'input-error': formErrors['cachePreviewsSize'] }"
+          >
+          <div *ngIf="formErrors.cachePreviewsSize" class="form-error">
+            {{ formErrors.cachePreviewsSize }}
+          </div>
         </div>
-      </div>
-
-      <div i18n class="inner-form-title">Customizations</div>
-
-      <div class="form-group">
-        <label i18n for="customizationJavascript">JavaScript</label>
-        <my-help
-          helpType="custom" i18n-customHtml
-          customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"
-        ></my-help>
-        <textarea
-          id="customizationJavascript" formControlName="customizationJavascript"
-          [ngClass]="{ 'input-error': formErrors['customizationJavascript'] }"
-        ></textarea>
-        <div *ngIf="formErrors.customizationJavascript" class="form-error">
-          {{ formErrors.customizationJavascript }}
+
+        <div class="form-group">
+          <label i18n for="cachePreviewsSize">Video captions cache size</label>
+          <input
+            type="text" id="cacheCaptionsSize"
+            formControlName="cacheCaptionsSize" [ngClass]="{ 'input-error': formErrors['cacheCaptionsSize'] }"
+          >
+          <div *ngIf="formErrors.cacheCaptionsSize" class="form-error">
+            {{ formErrors.cacheCaptionsSize }}
+          </div>
         </div>
-      </div>
-
-      <div class="form-group">
-        <label for="customizationCSS">CSS</label>
-        <my-help
-            helpType="custom"
-            i18n-customHtml
-            customHtml="
-              Write directly CSS code. Example:<br />
-              <pre>
-    body {{ '{' }}
-      background-color: red;
-    {{ '}' }}
-              </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="customizationCSS"
-          [ngClass]="{ 'input-error': formErrors['customizationCSS'] }"
-        ></textarea>
-        <div *ngIf="formErrors.customizationCSS" class="form-error">
-          {{ formErrors.customizationCSS }}
+
+        <div i18n class="inner-form-title">Customizations</div>
+
+        <div class="form-group">
+          <label i18n for="customizationJavascript">JavaScript</label>
+          <my-help
+            helpType="custom" i18n-customHtml
+            customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"
+          ></my-help>
+          <textarea
+            id="customizationJavascript" formControlName="customizationJavascript"
+            [ngClass]="{ 'input-error': formErrors['customizationJavascript'] }"
+          ></textarea>
+          <div *ngIf="formErrors.customizationJavascript" class="form-error">
+            {{ formErrors.customizationJavascript }}
+          </div>
         </div>
-      </div>
-    </tab>
-  </tabset>
+
+        <div class="form-group">
+          <label for="customizationCSS">CSS</label>
+          <my-help
+              helpType="custom"
+              i18n-customHtml
+              customHtml="
+                Write directly CSS code. Example:<br />
+                <pre>
+      body {{ '{' }}
+        background-color: red;
+      {{ '}' }}
+                </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="customizationCSS"
+            [ngClass]="{ 'input-error': formErrors['customizationCSS'] }"
+          ></textarea>
+          <div *ngIf="formErrors.customizationCSS" class="form-error">
+            {{ formErrors.customizationCSS }}
+          </div>
+        </div>
+      </ng-template>
+    </ngb-tab>
+  </ngb-tabset>
 
   <input (click)="formValidated()" type="submit" i18n-value value="Update configuration" [disabled]="!form.valid">
   <span class="form-error" i18n *ngIf="!form.valid">It seems the configuration is invalid. Please search potential errors in the different tabs.</span>
index 72635048c55e1d82d707f3613aed779b4a25046f..e08decb3f557e795d80f29788262c874c4b96648 100644 (file)
@@ -18,5 +18,5 @@
     It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
   </div>
 
-  <input type="submit" i18n-value value="Add following" [disabled]="hostsError || !hostsString" class="btn btn-default">
+  <input type="submit" i18n-value value="Add following" [disabled]="hostsError || !hostsString" class="btn btn-secondary">
 </form>
index a8258bf70a80b9c6d3546856bbcefd6ed20a0457..8eabb339210989296c5cab5c9a4bcbaaf5b90991 100644 (file)
@@ -1,13 +1,15 @@
 <div class="admin-sub-header">
   <div i18n class="form-sub-title">Manage follows</div>
 
-  <tabset #followsMenuTabs>
-    <tab *ngFor="let link of links">
-      <ng-template tabHeading>
+  <ngb-tabset #followsMenuTabs type="pills">
+
+    <ngb-tab *ngFor="let link of links">
+      <ng-template ngbTabTitle>
         <a class="tab-link" [routerLink]="link.path">{{ link.title }}</a>
       </ng-template>
-    </tab>
-  </tabset>
+    </ngb-tab>
+
+  </ngb-tabset>
 </div>
 
 <router-outlet></router-outlet>
index 08b3737f838ec1b5b9207b9b84b1898a73797b5b..766d7853b49e7a01c291854abd3d3f990682ca8f 100644 (file)
@@ -2,9 +2,3 @@
   flex-grow: 0;
   margin-right: 30px;
 }
-
-/deep/ .tab-content {
-  height: 0;
-  min-height: 0;
-  padding: 0;
-}
index f7af9826cd72defa1bc906c7acd2a9e6c67fe90f..b6f7715b38cf4d37303ffbe9f19136febc3bbff5 100644 (file)
@@ -1,14 +1,14 @@
 import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'
 import { NavigationEnd, Router } from '@angular/router'
-import { TabsetComponent } from 'ngx-bootstrap/tabs'
 import { I18n } from '@ngx-translate/i18n-polyfill'
+import { NgbTabset } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   templateUrl: './follows.component.html',
   styleUrls: [ './follows.component.scss' ]
 })
 export class FollowsComponent implements OnInit, AfterViewInit {
-  @ViewChild('followsMenuTabs') followsMenuTabs: TabsetComponent
+  @ViewChild('followsMenuTabs') followsMenuTabs: NgbTabset
 
   links: { path: string, title: string }[] = []
 
@@ -53,8 +53,8 @@ export class FollowsComponent implements OnInit, AfterViewInit {
     for (let i = 0; i < this.links.length; i++) {
       const path = this.links[i].path
 
-      if (url.endsWith(path) === true && this.followsMenuTabs.tabs[i]) {
-        this.followsMenuTabs.tabs[i].active = true
+      if (url.endsWith(path) === true) {
+        this.followsMenuTabs.select(path)
         return
       }
     }
index 0bb64cf009285c138cdd3139f2710ca8c8f1fefc..43f0c61907c096fbbd2a76726e5166127424759d 100644 (file)
@@ -1,31 +1,25 @@
-<div bsModal #confirmModal="bs-modal" [config]="{ animated: false }" class="modal" tabindex="-1" role="dialog">
-  <div class="modal-dialog">
-    <div class="modal-content">
+<ng-template #confirmModal let-close="close" let-dismiss="dismiss">
 
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="cancel()"></span>
-        <h4 class="modal-title">{{ title }}</h4>
-      </div>
+  <div class="modal-header">
+    <h4 class="modal-title">{{ title }}</h4>
+    <span class="close" aria-label="Close" role="button" (click)="dismiss()"></span>
+  </div>
 
-      <div class="modal-body" >
-        <div [innerHtml]="message"></div>
+  <div class="modal-body" >
+    <div [innerHtml]="message"></div>
 
-        <div *ngIf="inputLabel && expectedInputValue" class="form-group">
-          <label for="confirmInput">{{ inputLabel }}</label>
-          <input type="text" id="confirmInput" name="confirmInput" [(ngModel)]="inputValue" />
-        </div>
+    <div *ngIf="inputLabel && expectedInputValue" class="form-group">
+      <label for="confirmInput">{{ inputLabel }}</label>
+      <input type="text" id="confirmInput" name="confirmInput" [(ngModel)]="inputValue" />
+    </div>
+  </div>
 
-        <div class="form-group inputs">
-          <span i18n class="action-button action-button-cancel" (click)="cancel()">
-            Cancel
-          </span>
+  <div class="modal-footer inputs">
+    <span i18n class="action-button action-button-cancel" (click)="dismiss()" role="button">Cancel</span>
 
-          <input
-            type="submit" [value]="confirmButtonText" class="action-button-submit" [disabled]="isConfirmationDisabled()"
-            (click)="confirm()"
-          >
-        </div>
-      </div>
-    </div>
+    <input
+      type="submit" [value]="confirmButtonText" class="action-button-submit" [disabled]="isConfirmationDisabled()"
+      (click)="close()"
+    >
   </div>
-</div>
+</ng-template>
index a13152496a2de01955394b7ba2ff1bc243476be2..0d18c38e85870c1ee460100de7d3a57f2532838d 100644 (file)
@@ -1,9 +1,8 @@
-import { Component, HostListener, OnInit, ViewChild } from '@angular/core'
-
-import { ModalDirective } from 'ngx-bootstrap/modal'
-
+import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core'
 import { ConfirmService } from './confirm.service'
 import { I18n } from '@ngx-translate/i18n-polyfill'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
 
 @Component({
   selector: 'my-confirm',
@@ -11,7 +10,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
   styleUrls: [ './confirm.component.scss' ]
 })
 export class ConfirmComponent implements OnInit {
-  @ViewChild('confirmModal') confirmModal: ModalDirective
+  @ViewChild('confirmModal') confirmModal: ElementRef
 
   title = ''
   message = ''
@@ -21,7 +20,10 @@ export class ConfirmComponent implements OnInit {
   inputValue = ''
   confirmButtonText = ''
 
+  private openedModal: NgbModalRef
+
   constructor (
+    private modalService: NgbModal,
     private confirmService: ConfirmService,
     private i18n: I18n
   ) {
@@ -29,11 +31,6 @@ export class ConfirmComponent implements OnInit {
   }
 
   ngOnInit () {
-    this.confirmModal.config = {
-      backdrop: 'static',
-      keyboard: false
-    }
-
     this.confirmService.showConfirm.subscribe(
       ({ title, message, expectedInputValue, inputLabel, confirmButtonText }) => {
         this.title = title
@@ -49,16 +46,9 @@ export class ConfirmComponent implements OnInit {
     )
   }
 
-  @HostListener('keydown.enter')
+  @HostListener('document:keydown.enter')
   confirm () {
-    this.confirmService.confirmResponse.next(true)
-    this.hideModal()
-  }
-
-  @HostListener('keydown.esc')
-  cancel () {
-    this.confirmService.confirmResponse.next(false)
-    this.hideModal()
+    if (this.openedModal) this.openedModal.close()
   }
 
   isConfirmationDisabled () {
@@ -70,10 +60,11 @@ export class ConfirmComponent implements OnInit {
 
   showModal () {
     this.inputValue = ''
-    this.confirmModal.show()
-  }
 
-  hideModal () {
-    this.confirmModal.hide()
+    this.openedModal = this.modalService.open(this.confirmModal)
+
+    this.openedModal.result
+        .then(() => this.confirmService.confirmResponse.next(true))
+        .catch(() => this.confirmService.confirmResponse.next(false))
   }
 }
index c2de2084e87427a6c8726c74e22f60791f4dc8a6..30ac101191780e9e79bcb3d5404258c69fce9660 100644 (file)
@@ -8,7 +8,6 @@ import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client'
 import { LoadingBarRouterModule } from '@ngx-loading-bar/router'
 
 import { SimpleNotificationsModule } from 'angular2-notifications'
-import { ModalModule } from 'ngx-bootstrap/modal'
 
 import { AuthService } from './auth'
 import { ConfirmComponent, ConfirmService } from './confirm'
@@ -23,7 +22,6 @@ import { ServerService } from './server'
     FormsModule,
     BrowserAnimationsModule,
 
-    ModalModule,
     SimpleNotificationsModule.forRoot(),
 
     LoadingBarHttpClientModule,
index 1846fd19ed65efabce810e8eaf6d75b221994150..fac63d44d0d44ff651c2adb25b3338b0bb7b454b 100644 (file)
   </form>
 </div>
 
-<div bsModal #forgotPasswordModal="bs-modal" (onShown)="onForgotPasswordModalShown()" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hideForgotPasswordModal()"></span>
-        <h4 i18n class="modal-title">Forgot your password</h4>
-      </div>
+<!--<ng-template #forgotPasswordModal (onShown)="onForgotPasswordModalShown()">-->
+<ng-template #forgotPasswordModal>
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Forgot your password</h4>
+    <span class="close" aria-hidden="true" (click)="hideForgotPasswordModal()"></span>
+  </div>
 
-      <div class="modal-body">
-        <div class="form-group">
-          <label i18n for="forgot-password-email">Email</label>
-          <input
-            type="email" id="forgot-password-email" i18n-placeholder placeholder="Email address" required
-            [(ngModel)]="forgotPasswordEmail" #forgotPasswordEmailInput
-          >
-        </div>
+  <div class="modal-body">
+    <div class="form-group">
+      <label i18n for="forgot-password-email">Email</label>
+      <input
+        type="email" id="forgot-password-email" i18n-placeholder placeholder="Email address" required
+        [(ngModel)]="forgotPasswordEmail" #forgotPasswordEmailInput
+      >
+    </div>
+  </div>
 
-        <div class="form-group inputs">
-          <span i18n class="action-button action-button-cancel" (click)="hideForgotPasswordModal()">
-            Cancel
-          </span>
+  <div class="modal-footer inputs">
+    <span i18n class="action-button action-button-cancel" (click)="hideForgotPasswordModal()">Cancel</span>
 
-          <input
-            type="submit" i18n-value value="Send me an email to reset my password" class="action-button-submit"
-            (click)="askResetPassword()" [disabled]="!forgotPasswordEmailInput.validity.valid"
-          >
-        </div>
-      </div>
-    </div>
+    <input
+      type="submit" i18n-value value="Send me an email to reset my password" class="action-button-submit"
+      (click)="askResetPassword()" [disabled]="!forgotPasswordEmailInput.validity.valid"
+    >
   </div>
-</div>
+</ng-template>
index 9a68c12faa4d358c74d01f86c9130c08d1de6b87..8e88225108d3c615fdd8b2d38b7e3a56a972ce70 100644 (file)
@@ -2,12 +2,12 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
 import { RedirectService, ServerService } from '@app/core'
 import { UserService } from '@app/shared'
 import { NotificationsService } from 'angular2-notifications'
-import { ModalDirective } from 'ngx-bootstrap/modal'
 import { AuthService } from '../core'
 import { FormReactive } from '../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
 import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service'
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   selector: 'my-login',
@@ -16,14 +16,17 @@ import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-
 })
 
 export class LoginComponent extends FormReactive implements OnInit {
-  @ViewChild('forgotPasswordModal') forgotPasswordModal: ModalDirective
+  @ViewChild('forgotPasswordModal') forgotPasswordModal: ElementRef
   @ViewChild('forgotPasswordEmailInput') forgotPasswordEmailInput: ElementRef
 
   error: string = null
   forgotPasswordEmail = ''
 
+  private openedForgotPasswordModal: NgbModalRef
+
   constructor (
     protected formValidatorService: FormValidatorService,
+    private modalService: NgbModal,
     private loginValidatorsService: LoginValidatorsService,
     private authService: AuthService,
     private userService: UserService,
@@ -84,10 +87,10 @@ export class LoginComponent extends FormReactive implements OnInit {
   }
 
   openForgotPasswordModal () {
-    this.forgotPasswordModal.show()
+    this.openedForgotPasswordModal = this.modalService.open(this.forgotPasswordModal)
   }
 
   hideForgotPasswordModal () {
-    this.forgotPasswordModal.hide()
+    this.openedForgotPasswordModal.close()
   }
 }
index f941e32f81e56adf193a76f1d5c69cbb18b05b45..c37bf28262acba3714f7080e9c598f7a04203789 100644 (file)
@@ -1,15 +1,10 @@
-<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hide()"></span>
-        <h4 i18n class="modal-title">Change the language</h4>
-      </div>
+<ng-template #modal let-hide="close">
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Change the language</h4>
+    <span class="close" aria-label="Close" role="button" (click)="hide()"></span>
+  </div>
 
-      <div class="modal-body" *ngFor="let lang of languages">
-        <a [href]="buildLanguageLink(lang)">{{ lang.label }}</a>
-      </div>
-    </div>
+  <div class="modal-body">
+    <a *ngFor="let lang of languages" [href]="buildLanguageLink(lang)">{{ lang.label }}</a>
   </div>
-</div>
+</ng-template>
index 30c70c6a25357a1ba8d8ba7dfef335e03fbdd754..944e86f461d3ee0e350d74f359b22f56dd39ae7e 100644 (file)
@@ -1,19 +1,12 @@
 @import '_variables';
 @import '_mixins';
 
-.modal {
-  z-index: 10005;
-}
-
-.modal-title {
-  text-align: center;
-}
-
 .modal-body {
   text-align: center;
 
   a {
+    display: block;
     font-size: 16px;
-    margin-top: 10px;
+    margin: 15px;
   }
 }
\ No newline at end of file
index 3de6a129d356f28156b541a7095be51a7b46349a..45fa73e762a15dea6a001badc95d1e1a166afd85 100644 (file)
@@ -1,6 +1,6 @@
-import { Component, ViewChild } from '@angular/core'
-import { ModalDirective } from 'ngx-bootstrap/modal'
+import { Component, ElementRef, ViewChild } from '@angular/core'
 import { I18N_LOCALES } from '../../../../shared'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   selector: 'my-language-chooser',
@@ -8,21 +8,17 @@ import { I18N_LOCALES } from '../../../../shared'
   styleUrls: [ './language-chooser.component.scss' ]
 })
 export class LanguageChooserComponent {
-  @ViewChild('modal') modal: ModalDirective
+  @ViewChild('modal') modal: ElementRef
 
-  languages: { [ id: string ]: string }[] = []
+  languages: { id: string, label: string }[] = []
 
-  constructor () {
+  constructor (private modalService: NgbModal) {
     this.languages = Object.keys(I18N_LOCALES)
       .map(k => ({ id: k, label: I18N_LOCALES[k] }))
   }
 
   show () {
-    this.modal.show()
-  }
-
-  hide () {
-    this.modal.hide()
+    this.modalService.open(this.modal)
   }
 
   buildLanguageLink (lang: { id: string }) {
index c487a6fc1caba11a9b62d1fd98f2c2c344363f63..9657e5269081e05a1c6f8e4fec9b9f11300f6f6f 100644 (file)
           <div class="logged-in-email">{{ user.username }}</div>
         </div>
 
-        <div class="logged-in-more" dropdown placement="right" container="body">
-          <span class="glyphicon glyphicon-option-vertical" dropdownToggle></span>
+        <div class="logged-in-more" ngbDropdown placement="bottom-right">
+          <span class="glyphicon glyphicon-option-vertical" ngbDropdownToggle role="button"></span>
 
-          <ul *dropdownMenu class="dropdown-menu">
-            <li>
-              <a i18n [routerLink]="[ '/accounts', user.account?.nameWithHost ]" class="dropdown-item" title="My public profile">
-               My public profile
-              </a>
+          <div ngbDropdownMenu>
+            <a *ngIf="user.account" i18n [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="dropdown-item">
+             My public profile
+            </a>
 
-              <a i18n routerLink="/my-account" class="dropdown-item" title="My account">
-                My account
-              </a>
+            <a i18n routerLink="/my-account" class="dropdown-item">
+              My account
+            </a>
 
-              <a i18n (click)="logout($event)" class="dropdown-item" title="Log out" href="#">
-                Log out
-              </a>
-            </li>
-          </ul>
+            <a i18n (click)="logout($event)" class="dropdown-item" href="#">
+              Log out
+            </a>
+          </div>
         </div>
       </div>
 
index e61f4acd33fbce7e3e167c46777f1d8a18af6a37..39f1e9be0f2d77cd1864c95d83f08a730f09d339 100644 (file)
@@ -69,6 +69,10 @@ menu {
       .glyphicon {
         cursor: pointer;
         font-size: 18px;
+
+        &::after {
+          border: none;
+        }
       }
     }
   }
index 7fb2d4f7d7bca41da8af6e3bf014d7b8fe365857..bbc70f772dd41407e1b0472d30312264ba459535 100644 (file)
@@ -17,7 +17,7 @@
       </div>
     </div>
 
-    <div class="results-filter" [collapse]="isSearchFilterCollapsed">
+    <div class="results-filter" [ngbCollapse]="isSearchFilterCollapsed">
       <my-search-filters [advancedSearch]="advancedSearch" (filtered)="onFiltered()"></my-search-filters>
     </div>
   </div>
index 488046cf1fc2363e7bd48be5aad963f74335d3cb..5a715fb8e80e260d0260548763e77d365ea933fa 100644 (file)
@@ -4,14 +4,14 @@ import { SearchComponent } from '@app/search/search.component'
 import { SearchService } from '@app/search/search.service'
 import { SearchRoutingModule } from '@app/search/search-routing.module'
 import { SearchFiltersComponent } from '@app/search/search-filters.component'
-import { CollapseModule } from 'ngx-bootstrap/collapse'
+import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'
 
 @NgModule({
   imports: [
     SearchRoutingModule,
     SharedModule,
 
-    CollapseModule.forRoot()
+    NgbCollapseModule.forRoot()
   ],
 
   declarations: [
index 802562dd773e9f426f5ea6bd74d442c785b7a469..3de3b6fcdc41cc4c24f3b98f0d04ed96293511ca 100644 (file)
@@ -5,8 +5,13 @@
     id="description" name="description">
   </textarea>
 
-  <tabset *ngIf="arePreviewsDisplayed()" class="previews">
-    <tab *ngIf="truncate !== undefined" i18n-heading heading="Truncated preview" [innerHTML]="truncatedPreviewHTML"></tab>
-    <tab i18n-heading heading="Complete preview" [innerHTML]="previewHTML"></tab>
-  </tabset>
+  <ngb-tabset *ngIf="arePreviewsDisplayed()" class="previews" type="pills">
+    <ngb-tab *ngIf="truncate !== undefined" i18n-title title="Truncated preview">
+      <ng-template ngbTabContent><div [innerHTML]="truncatedPreviewHTML"></div></ng-template>
+    </ngb-tab>
+
+    <ngb-tab i18n-title title="Complete preview">
+      <ng-template ngbTabContent><div [innerHTML]="previewHTML"></div></ng-template>
+    </ngb-tab>
+  </ngb-tabset>
 </div>
index 1c3863e5236544f3f540a76af9732bdf1f80fbff..42a92d7f0f6052553fb489aa2866bbd5eba429c7 100644 (file)
@@ -18,9 +18,8 @@
   title="Get help"
   i18n-title
   [attr.aria-pressed]="isPopoverOpened"
-  [popover]="tooltipTemplate"
+  [ngbPopover]="tooltipTemplate"
   [placement]="tooltipPlacement"
-  [outsideClick]="true"
   (onHidden)="onPopoverHidden()"
   (onShown)="onPopoverShown()"
 ></span>
index 94de3af9f42a2d0965a801444dda70e0aeba36f8..ea7f2c88769309f0f9cb7a0942a41be837fdf24f 100644 (file)
@@ -8,11 +8,6 @@ import { HelpComponent } from '@app/shared/misc/help.component'
 import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
 import { MarkdownService } from '@app/videos/shared'
 
-import { BsDropdownModule } from 'ngx-bootstrap/dropdown'
-import { ModalModule } from 'ngx-bootstrap/modal'
-import { PopoverModule } from 'ngx-bootstrap/popover'
-import { TabsModule } from 'ngx-bootstrap/tabs'
-import { TooltipModule } from 'ngx-bootstrap/tooltip'
 import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
 import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared'
 
@@ -53,6 +48,7 @@ import { VideoCaptionService } from '@app/shared/video-caption'
 import { PeertubeCheckboxComponent } from '@app/shared/forms/peertube-checkbox.component'
 import { VideoImportService } from '@app/shared/video-import/video-import.service'
 import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component'
+import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
 
 @NgModule({
   imports: [
@@ -62,11 +58,11 @@ import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.com
     RouterModule,
     HttpClientModule,
 
-    BsDropdownModule.forRoot(),
-    ModalModule.forRoot(),
-    PopoverModule.forRoot(),
-    TabsModule.forRoot(),
-    TooltipModule.forRoot(),
+    NgbDropdownModule.forRoot(),
+    NgbModalModule.forRoot(),
+    NgbPopoverModule.forRoot(),
+    NgbTabsetModule.forRoot(),
+    NgbTooltipModule.forRoot(),
 
     PrimeSharedModule,
     NgPipesModule
@@ -97,11 +93,12 @@ import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.com
     RouterModule,
     HttpClientModule,
 
-    BsDropdownModule,
-    ModalModule,
-    PopoverModule,
-    TabsModule,
-    TooltipModule,
+    NgbDropdownModule,
+    NgbModalModule,
+    NgbPopoverModule,
+    NgbTabsetModule,
+    NgbTooltipModule,
+
     PrimeSharedModule,
     BytesPipe,
     KeysPipe,
index 5ef13e1ed9d108315f6a22e3658ca381deb9ebb4..2e687a7b9e993235d476daa84b491dd6a1fda2d0 100644 (file)
@@ -1,13 +1,10 @@
 <div class="video-feed">
-  <span *ngIf="syndicationItems.length !== 0" class="icon icon-syndication"
-    [popover]="feedsList"
-    placement="bottom"
-    [outsideClick]="true">
-  </span>
+  <span
+    *ngIf="syndicationItems.length !== 0" [ngbPopover]="feedsList" placement="bottom"
+    class="icon icon-syndication" role="button"
+  ></span>
 
   <ng-template #feedsList>
-    <div *ngFor="let item of syndicationItems">
-      <a [href]="item.url" target="_blank" rel="noopener noreferrer">{{ item.label }}</a>
-    </div>
+    <a *ngFor="let item of syndicationItems" [href]="item.url" target="_blank" rel="noopener noreferrer">{{ item.label }}</a>
   </ng-template>
 </div>
\ No newline at end of file
index 2efeb405e56917c66f44ca5d17e46680b6588d13..a5d1aabf7fac25a729633b1029616d338a438197 100644 (file)
@@ -5,6 +5,7 @@
     @include disable-default-a-behaviour;
 
     color: black;
+    display: block;
   }
 
   .icon {
index 9cd303b296c191300a8a95c931983ef8ccfcf9d7..30aefdbfc89be07a137fcfe9cfd552f5d075660e 100644 (file)
@@ -1,47 +1,45 @@
-<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content" [formGroup]="form">
+<ng-template #modal>
+  <ng-container [formGroup]="form">
 
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hide()"></span>
-        <h4 i18n class="modal-title">Add caption</h4>
-      </div>
+    <div class="modal-header">
+      <h4 i18n class="modal-title">Add caption</h4>
+      <span class="close" aria-label="Close" role="button" (click)="hide()"></span>
+    </div>
 
-      <div class="modal-body">
-        <label i18n for="language">Language</label>
-        <div class="peertube-select-container">
-          <select id="language" formControlName="language">
-            <option></option>
-            <option *ngFor="let language of videoCaptionLanguages" [value]="language.id">{{ language.label }}</option>
-          </select>
-        </div>
+    <div class="modal-body">
+      <label i18n for="language">Language</label>
+      <div class="peertube-select-container">
+        <select id="language" formControlName="language">
+          <option></option>
+          <option *ngFor="let language of videoCaptionLanguages" [value]="language.id">{{ language.label }}</option>
+        </select>
+      </div>
 
-        <div *ngIf="formErrors.language" class="form-error">
-          {{ formErrors.language }}
-        </div>
+      <div *ngIf="formErrors.language" class="form-error">
+        {{ formErrors.language }}
+      </div>
 
-        <div class="caption-file">
-          <my-reactive-file
-            formControlName="captionfile" inputName="captionfile" i18n-inputLabel inputLabel="Select the caption file"
-            [extensions]="videoCaptionExtensions" [maxFileSize]="videoCaptionMaxSize" [displayFilename]="true"
-          ></my-reactive-file>
-        </div>
+      <div class="caption-file">
+        <my-reactive-file
+          formControlName="captionfile" inputName="captionfile" i18n-inputLabel inputLabel="Select the caption file"
+          [extensions]="videoCaptionExtensions" [maxFileSize]="videoCaptionMaxSize" [displayFilename]="true"
+        ></my-reactive-file>
+      </div>
 
-        <div *ngIf="isReplacingExistingCaption()" class="warning-replace-caption" i18n>
-          This will replace an existing caption!
-        </div>
+      <div *ngIf="isReplacingExistingCaption()" class="warning-replace-caption" i18n>
+        This will replace an existing caption!
+      </div>
+    </div>
 
-        <div class="form-group inputs">
-          <span i18n class="action-button action-button-cancel" (click)="hide()">
-            Cancel
-          </span>
+    <div class="modal-footer inputs">
+      <span i18n class="action-button action-button-cancel" (click)="hide()">
+        Cancel
+      </span>
 
-          <input
-            type="submit" i18n-value value="Add this caption" class="action-button-submit"
-            [disabled]="!form.valid" (click)="addCaption()"
-          >
-        </div>
-      </div>
+      <input
+        type="submit" i18n-value value="Add this caption" class="action-button-submit"
+        [disabled]="!form.valid" (click)="addCaption()"
+      >
     </div>
-  </div>
-</div>
+  </ng-container>
+</ng-template>
index d084a490830a5dd50a494e148e204e54298634ea..07c33030aa7087fa904a88601a2b8b5f54ea4a6d 100644 (file)
@@ -1,10 +1,10 @@
-import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
-import { ModalDirective } from 'ngx-bootstrap/modal'
+import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
 import { FormReactive } from '@app/shared'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
 import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validators/video-captions-validators.service'
 import { ServerService } from '@app/core'
 import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   selector: 'my-video-caption-add-modal',
@@ -17,14 +17,16 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
 
   @Output() captionAdded = new EventEmitter<VideoCaptionEdit>()
 
-  @ViewChild('modal') modal: ModalDirective
+  @ViewChild('modal') modal: ElementRef
 
   videoCaptionLanguages = []
 
+  private openedModal: NgbModalRef
   private closingModal = false
 
   constructor (
     protected formValidatorService: FormValidatorService,
+    private modalService: NgbModal,
     private serverService: ServerService,
     private videoCaptionsValidatorsService: VideoCaptionsValidatorsService
   ) {
@@ -51,13 +53,12 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
   show () {
     this.closingModal = false
 
-    this.modal.show()
+    this.openedModal = this.modalService.open(this.modal, { keyboard: false })
   }
 
   hide () {
     this.closingModal = true
-
-    this.modal.hide()
+    this.openedModal.close()
   }
 
   isReplacingExistingCaption () {
index 2c40747baec38861c71fe85c9ebd5f043eed763f..26c9e977e5036ffe529bf87d8e54aa5fed12989e 100644 (file)
-<div class="video-edit row" [formGroup]="form">
-  <tabset class="root-tabset bootstrap">
-
-    <tab i18n-heading heading="Basic info">
-      <div class="col-md-8">
-        <div class="form-group">
-          <label i18n for="name">Title</label>
-          <input type="text" id="name" formControlName="name" />
-          <div *ngIf="formErrors.name" class="form-error">
-            {{ formErrors.name }}
+<div class="video-edit" [formGroup]="form">
+  <ngb-tabset class="root-tabset bootstrap">
+
+    <ngb-tab i18n-title title="Basic info">
+      <ng-template ngbTabContent>
+        <div class="row">
+          <div class="col-md-8">
+            <div class="form-group">
+              <label i18n for="name">Title</label>
+              <input type="text" id="name" formControlName="name" />
+              <div *ngIf="formErrors.name" class="form-error">
+                {{ formErrors.name }}
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label i18n class="label-tags">Tags</label> <span i18n>(press Enter to add)</span>
+              <tag-input
+                [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
+                formControlName="tags" maxItems="5" modelAsStrings="true"
+              ></tag-input>
+            </div>
+
+            <div class="form-group">
+              <label i18n for="description">Description</label>
+              <my-help helpType="markdownText" i18n-preHtml preHtml="Video descriptions are truncated by default and require manual action to expand them."></my-help>
+              <my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea>
+
+              <div *ngIf="formErrors.description" class="form-error">
+                {{ formErrors.description }}
+              </div>
+            </div>
           </div>
-        </div>
-
-        <div class="form-group">
-          <label i18n class="label-tags">Tags</label> <span i18n>(press Enter to add)</span>
-          <tag-input
-            [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
-            formControlName="tags" maxItems="5" modelAsStrings="true"
-          ></tag-input>
-        </div>
 
-        <div class="form-group">
-          <label i18n for="description">Description</label>
-          <my-help helpType="markdownText" i18n-preHtml preHtml="Video descriptions are truncated by default and require manual action to expand them."></my-help>
-          <my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea>
+          <div class="col-md-4">
+            <div class="form-group">
+              <label i18n>Channel</label>
+              <div class="peertube-select-container">
+                <select formControlName="channelId">
+                  <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
+                </select>
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label i18n for="category">Category</label>
+              <div class="peertube-select-container">
+                <select id="category" formControlName="category">
+                  <option></option>
+                  <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option>
+                </select>
+              </div>
+
+              <div *ngIf="formErrors.category" class="form-error">
+                {{ formErrors.category }}
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label i18n for="licence">Licence</label>
+              <div class="peertube-select-container">
+                <select id="licence" formControlName="licence">
+                  <option></option>
+                  <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option>
+                </select>
+              </div>
+
+              <div *ngIf="formErrors.licence" class="form-error">
+                {{ formErrors.licence }}
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label i18n for="language">Language</label>
+              <div class="peertube-select-container">
+                <select id="language" formControlName="language">
+                  <option></option>
+                  <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option>
+                </select>
+              </div>
+
+              <div *ngIf="formErrors.language" class="form-error">
+                {{ formErrors.language }}
+              </div>
+            </div>
+
+            <div class="form-group">
+              <label i18n for="privacy">Privacy</label>
+              <div class="peertube-select-container">
+                <select id="privacy" formControlName="privacy">
+                  <option></option>
+                  <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
+                  <option *ngIf="schedulePublicationPossible" [value]="SPECIAL_SCHEDULED_PRIVACY">Scheduled</option>
+                </select>
+              </div>
+
+              <div *ngIf="formErrors.privacy" class="form-error">
+                {{ formErrors.privacy }}
+              </div>
+            </div>
+
+            <div *ngIf="schedulePublicationEnabled" class="form-group">
+              <label i18n for="schedulePublicationAt">Schedule publication ({{ calendarTimezone }})</label>
+              <p-calendar
+                id="schedulePublicationAt" formControlName="schedulePublicationAt" [dateFormat]="calendarDateFormat"
+                [locale]="calendarLocale" [minDate]="minScheduledDate" [showTime]="true" [hideOnDateTimeSelect]="true"
+              >
+              </p-calendar>
+
+              <div *ngIf="formErrors.schedulePublicationAt" class="form-error">
+                {{ formErrors.schedulePublicationAt }}
+              </div>
+            </div>
+
+            <my-peertube-checkbox
+              inputName="nsfw" formControlName="nsfw"
+              i18n-labelText labelText="This video contains mature or explicit content"
+              i18n-helpHtml helpHtml="Some instances do not list videos containing mature or explicit content by default."
+            ></my-peertube-checkbox>
+
+            <my-peertube-checkbox
+              inputName="commentsEnabled" formControlName="commentsEnabled"
+              i18n-labelText labelText="Enable video comments"
+            ></my-peertube-checkbox>
+
+            <my-peertube-checkbox
+              inputName="waitTranscoding" formControlName="waitTranscoding"
+              i18n-labelText labelText="Wait transcoding before publishing the video"
+              i18n-helpHtml helpHtml="If you decide not to wait for transcoding before publishing the video, it could be unplayable until transcoding ends."
+            ></my-peertube-checkbox>
 
-          <div *ngIf="formErrors.description" class="form-error">
-            {{ formErrors.description }}
           </div>
         </div>
-      </div>
-
-      <div class="col-md-4">
-        <div class="form-group">
-          <label i18n>Channel</label>
-          <div class="peertube-select-container">
-            <select formControlName="channelId">
-              <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
-            </select>
+      </ng-template>
+    </ngb-tab>
+
+    <ngb-tab i18n-title title="Captions">
+      <ng-template ngbTabContent>
+        <div class="captions">
+
+          <div class="captions-header">
+            <a (click)="openAddCaptionModal()" class="create-caption">
+              <span class="icon icon-add"></span>
+              <ng-container i18n>Add another caption</ng-container>
+            </a>
           </div>
-        </div>
 
-        <div class="form-group">
-          <label i18n for="category">Category</label>
-          <div class="peertube-select-container">
-            <select id="category" formControlName="category">
-              <option></option>
-              <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option>
-            </select>
-          </div>
+          <div class="form-group" *ngFor="let videoCaption of videoCaptions">
 
-          <div *ngIf="formErrors.category" class="form-error">
-            {{ formErrors.category }}
-          </div>
-        </div>
+            <div class="caption-entry">
+              <ng-container *ngIf="!videoCaption.action">
+                <a
+                  i18n-title title="See the subtitle file" class="caption-entry-label" target="_blank" rel="noopener noreferrer"
+                  [href]="videoCaption.captionPath"
+                >{{ videoCaption.language.label }}</a>
 
-        <div class="form-group">
-          <label i18n for="licence">Licence</label>
-          <div class="peertube-select-container">
-            <select id="licence" formControlName="licence">
-              <option></option>
-              <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option>
-            </select>
-          </div>
+                <div class="caption-entry-state">Already uploaded      &#10004;</div>
 
-          <div *ngIf="formErrors.licence" class="form-error">
-            {{ formErrors.licence }}
-          </div>
-        </div>
+                <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Delete</span>
+              </ng-container>
 
-        <div class="form-group">
-          <label i18n for="language">Language</label>
-          <div class="peertube-select-container">
-            <select id="language" formControlName="language">
-              <option></option>
-              <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option>
-            </select>
-          </div>
+              <ng-container *ngIf="videoCaption.action === 'CREATE'">
+                <span class="caption-entry-label">{{ videoCaption.language.label }}</span>
 
-          <div *ngIf="formErrors.language" class="form-error">
-            {{ formErrors.language }}
-          </div>
-        </div>
+                <div class="caption-entry-state caption-entry-state-create">Will be created on update</div>
 
-        <div class="form-group">
-          <label i18n for="privacy">Privacy</label>
-          <div class="peertube-select-container">
-            <select id="privacy" formControlName="privacy">
-              <option></option>
-              <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
-              <option *ngIf="schedulePublicationPossible" [value]="SPECIAL_SCHEDULED_PRIVACY">Scheduled</option>
-            </select>
-          </div>
+                <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel create</span>
+              </ng-container>
 
-          <div *ngIf="formErrors.privacy" class="form-error">
-            {{ formErrors.privacy }}
-          </div>
-        </div>
+              <ng-container *ngIf="videoCaption.action === 'REMOVE'">
+                <span class="caption-entry-label">{{ videoCaption.language.label }}</span>
 
-        <div *ngIf="schedulePublicationEnabled" class="form-group">
-          <label i18n for="schedulePublicationAt">Schedule publication ({{ calendarTimezone }})</label>
-          <p-calendar
-            id="schedulePublicationAt" formControlName="schedulePublicationAt" [dateFormat]="calendarDateFormat"
-            [locale]="calendarLocale" [minDate]="minScheduledDate" [showTime]="true" [hideOnDateTimeSelect]="true"
-          >
-          </p-calendar>
+                <div class="caption-entry-state caption-entry-state-delete">Will be deleted on update</div>
 
-          <div *ngIf="formErrors.schedulePublicationAt" class="form-error">
-            {{ formErrors.schedulePublicationAt }}
+                <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel deletion</span>
+              </ng-container>
+            </div>
           </div>
-        </div>
 
-        <my-peertube-checkbox
-          inputName="nsfw" formControlName="nsfw"
-          i18n-labelText labelText="This video contains mature or explicit content"
-          i18n-helpHtml helpHtml="Some instances do not list videos containing mature or explicit content by default."
-        ></my-peertube-checkbox>
-
-        <my-peertube-checkbox
-          inputName="commentsEnabled" formControlName="commentsEnabled"
-          i18n-labelText labelText="Enable video comments"
-        ></my-peertube-checkbox>
-
-        <my-peertube-checkbox
-          inputName="waitTranscoding" formControlName="waitTranscoding"
-          i18n-labelText labelText="Wait transcoding before publishing the video"
-          i18n-helpHtml helpHtml="If you decide not to wait for transcoding before publishing the video, it could be unplayable until transcoding ends."
-        ></my-peertube-checkbox>
-
-      </div>
-    </tab>
-
-    <tab i18n-heading heading="Captions">
-      <div class="col-md-12 captions">
-
-        <div class="captions-header">
-          <a (click)="openAddCaptionModal()" class="create-caption">
-            <span class="icon icon-add"></span>
-            <ng-container i18n>Add another caption</ng-container>
-          </a>
-        </div>
-
-        <div class="form-group" *ngFor="let videoCaption of videoCaptions">
-
-          <div class="caption-entry">
-            <ng-container *ngIf="!videoCaption.action">
-              <a
-                i18n-title title="See the subtitle file" class="caption-entry-label" target="_blank" rel="noopener noreferrer"
-                [href]="videoCaption.captionPath"
-              >{{ videoCaption.language.label }}</a>
-
-              <div class="caption-entry-state">Already uploaded        &#10004;</div>
-
-              <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Delete</span>
-            </ng-container>
-
-            <ng-container *ngIf="videoCaption.action === 'CREATE'">
-              <span class="caption-entry-label">{{ videoCaption.language.label }}</span>
-
-              <div class="caption-entry-state caption-entry-state-create">Will be created on update</div>
-
-              <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel create</span>
-            </ng-container>
-
-            <ng-container *ngIf="videoCaption.action === 'REMOVE'">
-              <span class="caption-entry-label">{{ videoCaption.language.label }}</span>
-
-              <div class="caption-entry-state caption-entry-state-delete">Will be deleted on update</div>
-
-              <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel deletion</span>
-            </ng-container>
+          <div class="no-caption" *ngIf="videoCaptions?.length === 0">
+            No captions for now.
           </div>
-        </div>
-
-        <div class="no-caption" *ngIf="videoCaptions?.length === 0">
-          No captions for now.
-        </div>
 
-      </div>
-    </tab>
-
-    <tab i18n-heading heading="Advanced settings">
-      <div class="col-md-12 advanced-settings">
-        <div class="form-group">
-          <my-video-image
-            i18n-inputLabel inputLabel="Upload thumbnail" inputName="thumbnailfile" formControlName="thumbnailfile"
-            previewWidth="200px" previewHeight="110px"
-          ></my-video-image>
         </div>
+      </ng-template>
+    </ngb-tab>
+
+    <ngb-tab i18n-title title="Advanced settings">
+      <ng-template ngbTabContent>
+        <div class="advanced-settings">
+          <div class="form-group">
+            <my-video-image
+              i18n-inputLabel inputLabel="Upload thumbnail" inputName="thumbnailfile" formControlName="thumbnailfile"
+              previewWidth="200px" previewHeight="110px"
+            ></my-video-image>
+          </div>
 
-        <div class="form-group">
-          <my-video-image
-            i18n-inputLabel inputLabel="Upload preview" inputName="previewfile" formControlName="previewfile"
-            previewWidth="360px" previewHeight="200px"
-          ></my-video-image>
-        </div>
+          <div class="form-group">
+            <my-video-image
+              i18n-inputLabel inputLabel="Upload preview" inputName="previewfile" formControlName="previewfile"
+              previewWidth="360px" previewHeight="200px"
+            ></my-video-image>
+          </div>
 
-        <div class="form-group">
-          <label i18n for="support">Support</label>
-          <my-help helpType="markdownEnhanced" i18n-preHtml preHtml="Short text to tell people how they can support you (membership platform...)."></my-help>
-          <my-markdown-textarea
-            id="support" formControlName="support" textareaWidth="500px" [previewColumn]="true" markdownType="enhanced"
-            [classes]="{ 'input-error': formErrors['support'] }"
-          ></my-markdown-textarea>
-          <div *ngIf="formErrors.support" class="form-error">
-            {{ formErrors.support }}
+          <div class="form-group">
+            <label i18n for="support">Support</label>
+            <my-help helpType="markdownEnhanced" i18n-preHtml preHtml="Short text to tell people how they can support you (membership platform...)."></my-help>
+            <my-markdown-textarea
+              id="support" formControlName="support" textareaWidth="500px" [previewColumn]="true" markdownType="enhanced"
+              [classes]="{ 'input-error': formErrors['support'] }"
+            ></my-markdown-textarea>
+            <div *ngIf="formErrors.support" class="form-error">
+              {{ formErrors.support }}
+            </div>
           </div>
         </div>
-      </div>
-    </tab>
+      </ng-template>
+    </ngb-tab>
 
-  </tabset>
+  </ngb-tabset>
 
 </div>
 
index f3d9ee44acdd60a235a87938a466138d3ee604d9..4d18712310113dd1c12bbca21b5358606b4a9285 100644 (file)
       border: none;
       padding: 0;
       outline: 0;
+      color: inherit;
+      font-weight: $font-semibold;
     }
 
     .icon.icon-validate {
@@ -143,15 +145,7 @@ p-calendar {
 
 /deep/ {
   .root-tabset > .nav {
-    margin-left: 15px;
     margin-bottom: 15px;
-
-    .nav-link {
-      display: flex !important;
-      align-items: center;
-      height: 30px !important;
-      padding: 0 15px !important;
-    }
   }
 
   .ng2-tag-input {
index f6bd65fdcaf801658bbdc274b83ad5d4623499a2..f441d3fde4611eef4235e14787b8b3f6016c14c7 100644 (file)
@@ -1,5 +1,4 @@
 import { NgModule } from '@angular/core'
-import { TabsModule } from 'ngx-bootstrap/tabs'
 import { TagInputModule } from 'ngx-chips'
 import { SharedModule } from '../../../shared/'
 import { VideoEditComponent } from './video-edit.component'
@@ -23,7 +22,6 @@ import { VideoCaptionAddModalComponent } from './video-caption-add-modal.compone
 
   exports: [
     TagInputModule,
-    TabsModule,
     CalendarModule,
 
     VideoEditComponent
index 31b2f42289730257c6a46507633de5ead9429985..edd0541230299a593e211ecf7b13c3af0eabd4b9 100644 (file)
@@ -1,47 +1,42 @@
-<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hide()"></span>
-        <h4 i18n class="modal-title">Download video</h4>
-      </div>
-
-      <div class="modal-body">
-        <div class="peertube-select-container">
-          <select [(ngModel)]="resolutionId">
-            <option *ngFor="let file of video.files" [value]="file.resolution.id">{{ file.resolution.label }}</option>
-          </select>
-        </div>
+<ng-template #modal let-hide="close">
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Download video</h4>
+    <span class="close" aria-hidden="true" (click)="hide()"></span>
+  </div>
 
-        <div class="download-type">
-          <div class="peertube-radio-container">
-            <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
-            <label i18n for="download-direct">Direct download</label>
-          </div>
-          
-          <div class="peertube-radio-container">
-            <input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent">
-            <label i18n for="download-torrent">Torrent (.torrent file)</label>
-          </div>
+  <div class="modal-body">
+    <div class="peertube-select-container">
+      <select [(ngModel)]="resolutionId">
+        <option *ngFor="let file of video.files" [value]="file.resolution.id">{{ file.resolution.label }}</option>
+      </select>
+    </div>
 
-          <div class="peertube-radio-container">
-            <input type="radio" name="download" id="download-magnet" [(ngModel)]="downloadType" value="magnet">
-            <label i18n for="download-magnet">Torrent (magnet link)</label>
-          </div>
-        </div>
+    <div class="download-type">
+      <div class="peertube-radio-container">
+        <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
+        <label i18n for="download-direct">Direct download</label>
+      </div>
 
-        <div class="form-group inputs">
-          <span i18n class="action-button action-button-cancel" (click)="hide()">
-            Cancel
-          </span>
+      <div class="peertube-radio-container">
+        <input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent">
+        <label i18n for="download-torrent">Torrent (.torrent file)</label>
+      </div>
 
-          <input
-            type="submit" i18n-value value="Download" class="action-button-submit"
-            (click)="download()"
-          >
-        </div>
+      <div class="peertube-radio-container">
+        <input type="radio" name="download" id="download-magnet" [(ngModel)]="downloadType" value="magnet">
+        <label i18n for="download-magnet">Torrent (magnet link)</label>
       </div>
     </div>
   </div>
-</div>
+
+  <div class="modal-footer inputs">
+    <span i18n class="action-button action-button-cancel" (click)="hide()">
+      Cancel
+    </span>
+
+    <input
+      type="submit" i18n-value value="Download" class="action-button-submit"
+      (click)="download()"
+    >
+  </div>
+</ng-template>
index 2de706e47a707bd0b253f22aa4ca28b60e088fac..1361146dd774521d2aa839a8334178b5b1e9a595 100644 (file)
@@ -1,6 +1,6 @@
-import { Component, Input, OnInit, ViewChild } from '@angular/core'
-import { ModalDirective } from 'ngx-bootstrap/modal'
+import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'
 import { VideoDetails } from '../../../shared/video/video-details.model'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   selector: 'my-video-download',
@@ -10,12 +10,12 @@ import { VideoDetails } from '../../../shared/video/video-details.model'
 export class VideoDownloadComponent implements OnInit {
   @Input() video: VideoDetails = null
 
-  @ViewChild('modal') modal: ModalDirective
+  @ViewChild('modal') modal: ElementRef
 
   downloadType: 'direct' | 'torrent' | 'magnet' = 'torrent'
   resolutionId: number | string = -1
 
-  constructor () {
+  constructor (private modalService: NgbModal) {
     // empty
   }
 
@@ -24,11 +24,7 @@ export class VideoDownloadComponent implements OnInit {
   }
 
   show () {
-    this.modal.show()
-  }
-
-  hide () {
-    this.modal.hide()
+    this.modalService.open(this.modal)
   }
 
   download () {
index 4ee3721fbce2770134a8ab448b0edfe4ed89e8c9..8d9a492766ef9b2a26d81349aa08db7338ed9dce 100644 (file)
@@ -1,36 +1,31 @@
-<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hide()"></span>
-        <h4 i18n class="modal-title">Report video</h4>
-      </div>
-
-      <div class="modal-body">
+<ng-template #modal>
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Report video</h4>
+    <span class="close" aria-label="Close" role="button" (click)="hide()"></span>
+  </div>
 
-        <form novalidate [formGroup]="form" (ngSubmit)="report()">
-          <div class="form-group">
-            <textarea i18n-placeholder placeholder="Reason..." formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }">
-            </textarea>
-            <div *ngIf="formErrors.reason" class="form-error">
-              {{ formErrors.reason }}
-            </div>
-          </div>
+  <div class="modal-body">
 
-          <div class="form-group inputs">
-            <span i18n class="action-button action-button-cancel" (click)="hide()">
-              Cancel
-            </span>
+    <form novalidate [formGroup]="form" (ngSubmit)="report()">
+      <div class="form-group">
+        <textarea i18n-placeholder placeholder="Reason..." formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }">
+        </textarea>
+        <div *ngIf="formErrors.reason" class="form-error">
+          {{ formErrors.reason }}
+        </div>
+      </div>
 
-            <input
-              type="submit" i18n-value value="Submit" class="action-button-submit"
-              [disabled]="!form.valid"
-            >
-          </div>
-        </form>
+      <div class="form-group inputs">
+        <span i18n class="action-button action-button-cancel" (click)="hide()">
+          Cancel
+        </span>
 
+        <input
+          type="submit" i18n-value value="Submit" class="action-button-submit"
+          [disabled]="!form.valid"
+        >
       </div>
-    </div>
+    </form>
+
   </div>
-</div>
+</ng-template>
index d9768fdac830e3e5947bd5f310aa41a0480c3a84..297afb19f45a227f838a97a596855f753c0bf118 100644 (file)
@@ -1,11 +1,12 @@
 import { Component, Input, OnInit, ViewChild } from '@angular/core'
 import { NotificationsService } from 'angular2-notifications'
-import { ModalDirective } from 'ngx-bootstrap/modal'
 import { FormReactive, VideoAbuseService } from '../../../shared/index'
 import { VideoDetails } from '../../../shared/video/video-details.model'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
 import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/video-abuse-validators.service'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
 
 @Component({
   selector: 'my-video-report',
@@ -15,12 +16,15 @@ import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/v
 export class VideoReportComponent extends FormReactive implements OnInit {
   @Input() video: VideoDetails = null
 
-  @ViewChild('modal') modal: ModalDirective
+  @ViewChild('modal') modal: NgbModal
 
   error: string = null
 
+  private openedModal: NgbModalRef
+
   constructor (
     protected formValidatorService: FormValidatorService,
+    private modalService: NgbModal,
     private videoAbuseValidatorsService: VideoAbuseValidatorsService,
     private videoAbuseService: VideoAbuseService,
     private notificationsService: NotificationsService,
@@ -36,11 +40,12 @@ export class VideoReportComponent extends FormReactive implements OnInit {
   }
 
   show () {
-    this.modal.show()
+    this.openedModal = this.modalService.open(this.modal, { keyboard: false })
   }
 
   hide () {
-    this.modal.hide()
+    this.openedModal.close()
+    this.openedModal = null
   }
 
   report () {
index 74a3a57d4f49c9d4862fc0303315f8d44a0b0d40..02f5f0f44872ba7cf41595d887163de42ffa1929 100644 (file)
@@ -1,52 +1,46 @@
-<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hide()"></span>
-        <h4 i18n class="modal-title">Share</h4>
-      </div>
-
-      <div class="modal-body">
-        <div class="form-group">
-          <label i18n>URL</label>
-          <div class="input-group input-group-sm">
-            <input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoUrl()" />
-            <div class="input-group-btn" placement="bottom right">
-              <button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-default btn-search">
-                <span class="glyphicon glyphicon-copy"></span>
-              </button>
-            </div>
-          </div>
-        </div>
+<ng-template #modal let-hide="close">
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Share</h4>
+    <span class="close" aria-hidden="true" (click)="hide()"></span>
+  </div>
 
-        <div class="form-group">
-          <label i18n>Embed</label>
-          <div class="input-group input-group-sm">
-            <input #shareInput (click)="shareInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoIframeCode()" />
-            <div class="input-group-btn" placement="bottom right">
-              <button [ngxClipboard]="shareInput" (click)="activateCopiedMessage()" type="button" class="btn btn-default btn-search">
-                <span class="glyphicon glyphicon-copy"></span>
-              </button>
-            </div>
-          </div>
+  <div class="modal-body">
+    <div class="form-group">
+      <label i18n>URL</label>
+      <div class="input-group input-group-sm">
+        <input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoUrl()" />
+        <div class="input-group-append">
+          <button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
+            <span class="glyphicon glyphicon-copy"></span>
+          </button>
         </div>
+      </div>
+    </div>
 
-        <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).
+    <div class="form-group">
+      <label i18n>Embed</label>
+      <div class="input-group input-group-sm">
+        <input #shareInput (click)="shareInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoIframeCode()" />
+        <div class="input-group-append">
+          <button [ngxClipboard]="shareInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
+            <span class="glyphicon glyphicon-copy"></span>
+          </button>
         </div>
+      </div>
+    </div>
 
-        <div class="form-group qr-code-group">
-          <label i18n>QR-Code</label>
-          <ngx-qrcode qrc-element-type="url" [qrc-value]="getVideoUrl()" qrc-errorCorrectionLevel="Q"></ngx-qrcode>
-        </div>
+    <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).
+    </div>
 
-        <div class="form-group inputs">
-          <span i18n class="action-button action-button-cancel" (click)="hide()">
-            Cancel
-          </span>
-        </div>
-      </div>
+    <div class="form-group qr-code-group">
+      <label i18n>QR-Code</label>
+      <ngx-qrcode qrc-element-type="url" [qrc-value]="getVideoUrl()" qrc-errorCorrectionLevel="Q"></ngx-qrcode>
     </div>
   </div>
-</div>
+
+  <div class="modal-footer inputs">
+    <span i18n class="action-button action-button-cancel" (click)="hide()">Cancel</span>
+  </div>
+
+</ng-template>
index c7f30bec5882c90c2bbaeac5c71db5727c49e50c..a9e9b84985b8030adcb9a74d395b23886d0f0606 100644 (file)
@@ -1,7 +1,14 @@
+@import '~bootstrap/scss/functions';
+@import '~bootstrap/scss/variables';
+
 .action-button-cancel {
   margin-right: 0 !important;
 }
 
+.btn-outline-secondary {
+  border-color: $input-border-color;
+}
+
 .qr-code-group {
   text-align: center;
 }
index 5c988a43b51fb3797d7a53ce116b8cc6bdd1189e..14f557f9acb608f467e7558434bd40dbb0a38243 100644 (file)
@@ -1,11 +1,9 @@
-import { Component, Input, ViewChild } from '@angular/core'
-
+import { Component, ElementRef, Input, ViewChild } from '@angular/core'
 import { NotificationsService } from 'angular2-notifications'
-
-import { ModalDirective } from 'ngx-bootstrap/modal'
 import { VideoDetails } from '../../../shared/video/video-details.model'
 import { buildVideoEmbed } from '../../../../assets/player/utils'
 import { I18n } from '@ngx-translate/i18n-polyfill'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   selector: 'my-video-share',
@@ -15,9 +13,10 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
 export class VideoShareComponent {
   @Input() video: VideoDetails = null
 
-  @ViewChild('modal') modal: ModalDirective
+  @ViewChild('modal') modal: ElementRef
 
   constructor (
+    private modalService: NgbModal,
     private notificationsService: NotificationsService,
     private i18n: I18n
   ) {
@@ -25,11 +24,7 @@ export class VideoShareComponent {
   }
 
   show () {
-    this.modal.show()
-  }
-
-  hide () {
-    this.modal.hide()
+    this.modalService.open(this.modal)
   }
 
   getVideoIframeCode () {
index 9bcfcea477c71e6c162e941f51e90f8e39685a5a..00c30470967ea05eca7dc547659878335660c9ca 100644 (file)
@@ -1,22 +1,12 @@
-<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog">
-    <div class="modal-content">
-
-      <div class="modal-header">
-        <span class="close" aria-hidden="true" (click)="hide()"></span>
-        <h4 i18n class="modal-title">Support</h4>
-      </div>
-
-      <div class="modal-body">
+<ng-template #modal let-hide="close">
+  <div class="modal-header">
+    <h4 i18n class="modal-title">Support</h4>
+    <span class="close" aria-label="Close" role="button" (click)="hide()"></span>
+  </div>
 
-        <div [innerHTML]="videoHTMLSupport"></div>
+  <div class="modal-body" [innerHTML]="videoHTMLSupport"></div>
 
-        <div class="form-group inputs">
-          <span i18n class="action-button action-button-cancel" (click)="hide()">
-            Cancel
-          </span>
-        </div>
-      </div>
-    </div>
+  <div class="modal-footer inputs">
+    <span i18n class="action-button action-button-cancel" (click)="hide()">Cancel</span>
   </div>
-</div>
+</ng-template>
index c515298a07d5fd32fdd302625ed42b20f93229c4..2d400e0be342bfb02c644ec376677f8b77ae90a2 100644 (file)
@@ -1,8 +1,8 @@
 import { Component, Input, ViewChild } from '@angular/core'
 import { MarkdownService } from '@app/videos/shared'
 
-import { ModalDirective } from 'ngx-bootstrap/modal'
 import { VideoDetails } from '../../../shared/video/video-details.model'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
 
 @Component({
   selector: 'my-video-support',
@@ -12,21 +12,19 @@ import { VideoDetails } from '../../../shared/video/video-details.model'
 export class VideoSupportComponent {
   @Input() video: VideoDetails = null
 
-  @ViewChild('modal') modal: ModalDirective
+  @ViewChild('modal') modal: NgbModal
 
   videoHTMLSupport = ''
 
-  constructor (private markdownService: MarkdownService) {
+  constructor (
+    private markdownService: MarkdownService,
+    private modalService: NgbModal
+  ) {
     // empty
   }
 
   show () {
-    this.modal.show()
-
     this.videoHTMLSupport = this.markdownService.enhancedMarkdownToHTML(this.video.support)
-  }
-
-  hide () {
-    this.modal.hide()
+    this.modalService.open(this.modal)
   }
 }
index 5a132112d920f17148a296a94d7eafb890d8bae9..dd0d628bdd524c7a1adb23421274f75943aa332a 100644 (file)
               <span class="icon-text" i18n>Share</span>
             </div>
 
-            <div class="action-more" dropdown dropup="true" placement="right" role="button">
-              <div class="action-button" dropdownToggle>
+            <div class="action-more" ngbDropdown placement="top" role="button">
+              <div class="action-button" ngbDropdownToggle role="button">
                 <span class="icon icon-more"></span>
               </div>
 
-              <ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button">
-                <li role="menuitem">
-                  <a class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
-                    <span class="icon icon-download"></span> <ng-container i18n>Download</ng-container>
-                  </a>
-                </li>
-
-                <li *ngIf="isUserLoggedIn()" role="menuitem">
-                  <a class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)">
-                    <span class="icon icon-alert"></span> <ng-container i18n>Report</ng-container>
-                  </a>
-                </li>
-
-                <li *ngIf="isVideoBlacklistable()" role="menuitem">
-                  <a class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="blacklistVideo($event)">
-                    <span class="icon icon-blacklist"></span> <ng-container i18n>Blacklist</ng-container>
-                  </a>
-                </li>
-
-                <li *ngIf="isVideoUpdatable()" role="menuitem">
-                  <a class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]">
-                    <span class="icon icon-edit"></span> <ng-container i18n>Update</ng-container>
-                  </a>
-                </li>
-
-                <li *ngIf="isVideoRemovable()" role="menuitem">
-                  <a class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)">
-                    <span class="icon icon-blacklist"></span> <ng-container i18n>Delete</ng-container>
-                  </a>
-                </li>
-              </ul>
+              <div ngbDropdownMenu>
+                <a class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
+                  <span class="icon icon-download"></span> <ng-container i18n>Download</ng-container>
+                </a>
+
+                <a *ngIf="isUserLoggedIn()" class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)">
+                  <span class="icon icon-alert"></span> <ng-container i18n>Report</ng-container>
+                </a>
+
+                <a *ngIf="isVideoBlacklistable()" class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="blacklistVideo($event)">
+                  <span class="icon icon-blacklist"></span> <ng-container i18n>Blacklist</ng-container>
+                </a>
+
+                <a *ngIf="isVideoUpdatable()" class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]">
+                  <span class="icon icon-edit"></span> <ng-container i18n>Update</ng-container>
+                </a>
+
+                <a *ngIf="isVideoRemovable()" class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)">
+                  <span class="icon icon-blacklist"></span> <ng-container i18n>Delete</ng-container>
+                </a>
+              </div>
             </div>
           </div>
 
           <div
               class="video-info-likes-dislikes-bar"
-              *ngIf="video.likes !== 0 || video.dislikes !== 0"  [tooltip]="likesBarTooltipText">
+              *ngIf="video.likes !== 0 || video.dislikes !== 0"  [ngbTooltip]="likesBarTooltipText">
             <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div>
           </div>
         </div>
index b27a70197dade594260bccde6182c4c9454ff79f..7d269b31f698a21ae3717eb9d08bf3f72e782eb8 100644 (file)
             padding: 0 10px 0 10px;
             white-space: nowrap;
 
+            &::after {
+              display: none;
+            }
+
             .icon {
               @include icon(21px);
 
index 4af9930435df30f3475d91d375060b208781d0d9..09d5133e4dfd3176712ffeefd42dfe6c37a98862 100644 (file)
@@ -1,7 +1,6 @@
 import { NgModule } from '@angular/core'
 import { LinkifierService } from '@app/videos/+video-watch/comment/linkifier.service'
 import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component'
-import { TooltipModule } from 'ngx-bootstrap/tooltip'
 import { ClipboardModule } from 'ngx-clipboard'
 import { SharedModule } from '../../shared'
 import { MarkdownService } from '../shared'
@@ -12,18 +11,17 @@ import { VideoCommentsComponent } from './comment/video-comments.component'
 import { VideoDownloadComponent } from './modal/video-download.component'
 import { VideoReportComponent } from './modal/video-report.component'
 import { VideoShareComponent } from './modal/video-share.component'
-
 import { VideoWatchRoutingModule } from './video-watch-routing.module'
-
 import { VideoWatchComponent } from './video-watch.component'
 import { NgxQRCodeModule } from 'ngx-qrcode2'
+import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
 
 @NgModule({
   imports: [
     VideoWatchRoutingModule,
     SharedModule,
     ClipboardModule,
-    TooltipModule.forRoot(),
+    NgbTooltipModule.forRoot(),
     NgxQRCodeModule
   ],
 
index 74759348e720e36290e7e149e30d20058d37e1ac..b120d409007bb7021aa8f80416e1fe28ba92295b 100644 (file)
@@ -42,6 +42,10 @@ input.readonly {
   background-color: #fff !important;
 }
 
+input, textarea {
+  outline: none;
+}
+
 label {
   font-weight: $font-bold;
   font-size: 15px;
@@ -174,9 +178,13 @@ label {
       @include icon(24px);
 
       position: relative;
-      right: -1px;
+      top: 3px;
       float: right;
       background-image: url('../assets/images/global/cross.svg');
+
+      margin: 0;
+      padding: 0;
+      opacity: 1;
     }
   }
 
@@ -200,47 +208,35 @@ label {
   }
 }
 
-tabset:not(.bootstrap) {
-  .nav {
-    font-size: 16px !important;
-    border: none !important;
+// Nav customizations
+.nav .nav-link {
+  display: flex !important;
+  align-items: center;
+  height: 30px !important;
+  padding: 10px 15px !important;
+}
 
-    .nav-item .nav-link {
-      margin-right: 30px;
-      padding: 0;
-      border-radius: 3px;
-      border: none !important;
-
-      .tab-link {
-        display: flex !important;
-        align-items: center;
-        min-height: 30px !important;
-        padding: 0 15px;
-      }
+.nav.nav-pills {
+  font-size: 16px !important;
 
-      &, & a {
-        color: #000 !important;
-        @include disable-default-a-behaviour;
-      }
+  .nav-link.active {
+    font-weight: $font-semibold !important;
+  }
 
-      &.active, &:hover {
-        background-color: #F0F0F0;
-      }
+  a {
+    @include disable-default-a-behaviour;
 
-      &.active {
-        font-weight: $font-semibold !important;
-      }
-    }
+    color: #000;
   }
 }
 
-tabset.bootstrap {
-  margin-left: 0;
+ngb-tabset.bootstrap {
 
-  .nav-item .nav-link {
+  .nav-link {
     &, & a {
-      color: #000;
       @include disable-default-a-behaviour;
+
+      color: #000 !important;
     }
   }
 }
index b56b71536cfb0dd102b6f8ee92581bf83dd5c2d3..5abec02d5a592e27056412bcc440f9d6c5531369 100644 (file)
@@ -1,37 +1,51 @@
-@import "~bootstrap/scss/functions";
-@import "~bootstrap/scss/variables";
-@import "~bootstrap/scss/mixins";
-@import "~bootstrap/scss/root";
-@import "~bootstrap/scss/reboot";
-@import "~bootstrap/scss/type";
-//@import "~bootstrap/scss/images";
-//@import "~bootstrap/scss/code";
-@import "~bootstrap/scss/grid";
-//@import "~bootstrap/scss/tables";
-@import "~bootstrap/scss/forms";
-@import "~bootstrap/scss/buttons";
-//@import "~bootstrap/scss/transitions";
-@import "~bootstrap/scss/dropdown";
-//@import "~bootstrap/scss/button-group";
-@import "~bootstrap/scss/input-group";
-//@import "~bootstrap/scss/custom-forms";
-@import "~bootstrap/scss/nav";
-//@import "~bootstrap/scss/navbar";
-//@import "~bootstrap/scss/card";
-//@import "~bootstrap/scss/breadcrumb";
-//@import "~bootstrap/scss/pagination";
-//@import "~bootstrap/scss/badge";
-//@import "~bootstrap/scss/jumbotron";
-@import "~bootstrap/scss/alert";
-//@import "~bootstrap/scss/progress";
-//@import "~bootstrap/scss/media";
-//@import "~bootstrap/scss/list-group";
-@import "~bootstrap/scss/close";
-@import "~bootstrap/scss/modal";
-@import "~bootstrap/scss/tooltip";
-@import "~bootstrap/scss/popover";
-//@import "~bootstrap/scss/carousel";
-//@import "~bootstrap/scss/utilities";
-//@import "~bootstrap/scss/print";
+$dropdown-link-active-bg: inherit;
 
-@import "~@neos21/bootstrap3-glyphicons/assets/stylesheets/bootstrap3-glyphicons";
\ No newline at end of file
+$zindex-modal: 10005;
+$modal-footer-border-width: 0;
+$modal-md: 600px;
+
+$input-btn-focus-width: 0;
+$input-btn-focus-color: inherit;
+$input-focus-border-color: #ced4da;
+
+$nav-pills-link-active-bg: #F0F0F0;
+$nav-pills-link-active-color: #000;
+
+@import '~bootstrap/scss/functions';
+@import '~bootstrap/scss/variables';
+
+@import '~bootstrap/scss/mixins';
+@import '~bootstrap/scss/root';
+@import '~bootstrap/scss/reboot';
+@import '~bootstrap/scss/type';
+//@import '~bootstrap/scss/images';
+//@import '~bootstrap/scss/code';
+@import '~bootstrap/scss/grid';
+//@import '~bootstrap/scss/tables';
+@import '~bootstrap/scss/forms';
+@import '~bootstrap/scss/buttons';
+//@import '~bootstrap/scss/transitions';
+@import '~bootstrap/scss/dropdown';
+//@import '~bootstrap/scss/button-group';
+@import '~bootstrap/scss/input-group';
+//@import '~bootstrap/scss/custom-forms';
+@import '~bootstrap/scss/nav';
+//@import '~bootstrap/scss/navbar';
+//@import '~bootstrap/scss/card';
+//@import '~bootstrap/scss/breadcrumb';
+//@import '~bootstrap/scss/pagination';
+//@import '~bootstrap/scss/badge';
+//@import '~bootstrap/scss/jumbotron';
+@import '~bootstrap/scss/alert';
+//@import '~bootstrap/scss/progress';
+//@import '~bootstrap/scss/media';
+//@import '~bootstrap/scss/list-group';
+@import '~bootstrap/scss/close';
+@import '~bootstrap/scss/modal';
+@import '~bootstrap/scss/tooltip';
+@import '~bootstrap/scss/popover';
+//@import '~bootstrap/scss/carousel';
+@import '~bootstrap/scss/utilities';
+//@import '~bootstrap/scss/print';
+
+@import '~@neos21/bootstrap3-glyphicons/assets/stylesheets/bootstrap3-glyphicons';
index 32c0f7ea3c709b74f2b0c920e4ef02de50f63343..f350416d6f6477cdebd421bb44b629c092cbef35 100644 (file)
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@neos21/bootstrap3-glyphicons/-/bootstrap3-glyphicons-1.0.1.tgz#e5eeec43e0153d4b51effd9ecb58cdf7029924d7"
 
+"@ng-bootstrap/ng-bootstrap@^2.2.2":
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-2.2.2.tgz#07c64badd48b563140eb5a6327b5516bf2226834"
+
 "@ngtools/webpack@6.1.1":
   version "6.1.1"
   resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-6.1.1.tgz#dcfea287c0c1358f3e123621c65b0e3ccaab5b70"
@@ -5350,10 +5354,6 @@ ng2-material-dropdown@0.10.1:
   dependencies:
     tslib "^1.9.0"
 
-ngx-bootstrap@3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.0.1.tgz#e98d2fc6340f32a9d358cd08e8fda7dcb23bdab3"
-
 ngx-chips@1.9.3:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/ngx-chips/-/ngx-chips-1.9.3.tgz#0ebc13b4868d9cd480478ed93fd56bcc3b68ea66"