Migrate to bootstrap 4 and ng-bootstrap

This commit is contained in:
Chocobozzz 2018-08-09 14:55:06 +02:00
parent b34a444e29
commit 63347a0ff9
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
44 changed files with 924 additions and 984 deletions

View File

@ -46,6 +46,7 @@
"@angular/service-worker": "~6.1.0", "@angular/service-worker": "~6.1.0",
"@angularclass/hmr": "^2.1.3", "@angularclass/hmr": "^2.1.3",
"@neos21/bootstrap3-glyphicons": "^1.0.1", "@neos21/bootstrap3-glyphicons": "^1.0.1",
"@ng-bootstrap/ng-bootstrap": "^2.2.2",
"@ngx-loading-bar/core": "^2.0.0", "@ngx-loading-bar/core": "^2.0.0",
"@ngx-loading-bar/http-client": "^2.0.0", "@ngx-loading-bar/http-client": "^2.0.0",
"@ngx-loading-bar/router": "^2.0.0", "@ngx-loading-bar/router": "^2.0.0",
@ -86,7 +87,6 @@
"linkifyjs": "^2.1.5", "linkifyjs": "^2.1.5",
"lodash-es": "^4.17.4", "lodash-es": "^4.17.4",
"markdown-it": "^8.4.0", "markdown-it": "^8.4.0",
"ngx-bootstrap": "3.0.1",
"ngx-chips": "1.9.3", "ngx-chips": "1.9.3",
"ngx-clipboard": "11.1.1", "ngx-clipboard": "11.1.1",
"ngx-pipes": "^2.1.7", "ngx-pipes": "^2.1.7",

View File

@ -1,7 +1,6 @@
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { ConfigComponent, EditCustomConfigComponent } from '@app/+admin/config' import { ConfigComponent, EditCustomConfigComponent } from '@app/+admin/config'
import { ConfigService } from '@app/+admin/config/shared/config.service' import { ConfigService } from '@app/+admin/config/shared/config.service'
import { TabsModule } from 'ngx-bootstrap/tabs'
import { TableModule } from 'primeng/table' import { TableModule } from 'primeng/table'
import { SharedModule } from '../shared' import { SharedModule } from '../shared'
import { AdminRoutingModule } from './admin-routing.module' import { AdminRoutingModule } from './admin-routing.module'
@ -18,7 +17,6 @@ import { VideoBlacklistComponent, VideoBlacklistListComponent } from './video-bl
@NgModule({ @NgModule({
imports: [ imports: [
AdminRoutingModule, AdminRoutingModule,
TabsModule.forRoot(),
TableModule, TableModule,
SharedModule SharedModule
], ],

View File

@ -1,8 +1,9 @@
<form role="form" [formGroup]="form"> <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>
@ -141,10 +142,11 @@
{{ formErrors.userVideoQuota }} {{ formErrors.userVideoQuota }}
</div> </div>
</div> </div>
</tab> </ng-template>
</ngb-tab>
<tab i18n-heading heading="Services">
<ngb-tab i18n-title title="Services">
<ng-template ngbTabContent>
<div i18n class="inner-form-title">Twitter</div> <div i18n class="inner-form-title">Twitter</div>
<div class="form-group"> <div class="form-group">
@ -166,12 +168,14 @@
inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted" inputName="servicesTwitterWhitelisted" formControlName="servicesTwitterWhitelisted"
i18n-labelText labelText="Instance whitelisted by Twitter" 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 /> 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 /> 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." 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> ></my-peertube-checkbox>
</tab> </ng-template>
</ngb-tab>
<tab i18n-heading heading="Advanced configuration"> <ngb-tab i18n-title title="Advanced configuration">
<ng-template ngbTabContent>
<div i18n class="inner-form-title">Transcoding</div> <div i18n class="inner-form-title">Transcoding</div>
@ -283,8 +287,9 @@ Check this checkbox, save the configuration and test with a video URL of your in
{{ formErrors.customizationCSS }} {{ formErrors.customizationCSS }}
</div> </div>
</div> </div>
</tab> </ng-template>
</tabset> </ngb-tab>
</ngb-tabset>
<input (click)="formValidated()" type="submit" i18n-value value="Update configuration" [disabled]="!form.valid"> <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> <span class="form-error" i18n *ngIf="!form.valid">It seems the configuration is invalid. Please search potential errors in the different tabs.</span>

View 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. It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</div> </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> </form>

View File

@ -1,13 +1,15 @@
<div class="admin-sub-header"> <div class="admin-sub-header">
<div i18n class="form-sub-title">Manage follows</div> <div i18n class="form-sub-title">Manage follows</div>
<tabset #followsMenuTabs> <ngb-tabset #followsMenuTabs type="pills">
<tab *ngFor="let link of links">
<ng-template tabHeading> <ngb-tab *ngFor="let link of links">
<ng-template ngbTabTitle>
<a class="tab-link" [routerLink]="link.path">{{ link.title }}</a> <a class="tab-link" [routerLink]="link.path">{{ link.title }}</a>
</ng-template> </ng-template>
</tab> </ngb-tab>
</tabset>
</ngb-tabset>
</div> </div>
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@ -2,9 +2,3 @@
flex-grow: 0; flex-grow: 0;
margin-right: 30px; margin-right: 30px;
} }
/deep/ .tab-content {
height: 0;
min-height: 0;
padding: 0;
}

View File

@ -1,14 +1,14 @@
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core' import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'
import { NavigationEnd, Router } from '@angular/router' import { NavigationEnd, Router } from '@angular/router'
import { TabsetComponent } from 'ngx-bootstrap/tabs'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { NgbTabset } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
templateUrl: './follows.component.html', templateUrl: './follows.component.html',
styleUrls: [ './follows.component.scss' ] styleUrls: [ './follows.component.scss' ]
}) })
export class FollowsComponent implements OnInit, AfterViewInit { export class FollowsComponent implements OnInit, AfterViewInit {
@ViewChild('followsMenuTabs') followsMenuTabs: TabsetComponent @ViewChild('followsMenuTabs') followsMenuTabs: NgbTabset
links: { path: string, title: string }[] = [] links: { path: string, title: string }[] = []
@ -53,8 +53,8 @@ export class FollowsComponent implements OnInit, AfterViewInit {
for (let i = 0; i < this.links.length; i++) { for (let i = 0; i < this.links.length; i++) {
const path = this.links[i].path const path = this.links[i].path
if (url.endsWith(path) === true && this.followsMenuTabs.tabs[i]) { if (url.endsWith(path) === true) {
this.followsMenuTabs.tabs[i].active = true this.followsMenuTabs.select(path)
return return
} }
} }

View File

@ -1,10 +1,8 @@
<div bsModal #confirmModal="bs-modal" [config]="{ animated: false }" class="modal" tabindex="-1" role="dialog"> <ng-template #confirmModal let-close="close" let-dismiss="dismiss">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="cancel()"></span>
<h4 class="modal-title">{{ title }}</h4> <h4 class="modal-title">{{ title }}</h4>
<span class="close" aria-label="Close" role="button" (click)="dismiss()"></span>
</div> </div>
<div class="modal-body" > <div class="modal-body" >
@ -14,18 +12,14 @@
<label for="confirmInput">{{ inputLabel }}</label> <label for="confirmInput">{{ inputLabel }}</label>
<input type="text" id="confirmInput" name="confirmInput" [(ngModel)]="inputValue" /> <input type="text" id="confirmInput" name="confirmInput" [(ngModel)]="inputValue" />
</div> </div>
</div>
<div class="form-group inputs"> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="cancel()"> <span i18n class="action-button action-button-cancel" (click)="dismiss()" role="button">Cancel</span>
Cancel
</span>
<input <input
type="submit" [value]="confirmButtonText" class="action-button-submit" [disabled]="isConfirmationDisabled()" type="submit" [value]="confirmButtonText" class="action-button-submit" [disabled]="isConfirmationDisabled()"
(click)="confirm()" (click)="close()"
> >
</div> </div>
</div> </ng-template>
</div>
</div>
</div>

View File

@ -1,9 +1,8 @@
import { Component, HostListener, OnInit, ViewChild } from '@angular/core' import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { ConfirmService } from './confirm.service' import { ConfirmService } from './confirm.service'
import { I18n } from '@ngx-translate/i18n-polyfill' 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({ @Component({
selector: 'my-confirm', selector: 'my-confirm',
@ -11,7 +10,7 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
styleUrls: [ './confirm.component.scss' ] styleUrls: [ './confirm.component.scss' ]
}) })
export class ConfirmComponent implements OnInit { export class ConfirmComponent implements OnInit {
@ViewChild('confirmModal') confirmModal: ModalDirective @ViewChild('confirmModal') confirmModal: ElementRef
title = '' title = ''
message = '' message = ''
@ -21,7 +20,10 @@ export class ConfirmComponent implements OnInit {
inputValue = '' inputValue = ''
confirmButtonText = '' confirmButtonText = ''
private openedModal: NgbModalRef
constructor ( constructor (
private modalService: NgbModal,
private confirmService: ConfirmService, private confirmService: ConfirmService,
private i18n: I18n private i18n: I18n
) { ) {
@ -29,11 +31,6 @@ export class ConfirmComponent implements OnInit {
} }
ngOnInit () { ngOnInit () {
this.confirmModal.config = {
backdrop: 'static',
keyboard: false
}
this.confirmService.showConfirm.subscribe( this.confirmService.showConfirm.subscribe(
({ title, message, expectedInputValue, inputLabel, confirmButtonText }) => { ({ title, message, expectedInputValue, inputLabel, confirmButtonText }) => {
this.title = title this.title = title
@ -49,16 +46,9 @@ export class ConfirmComponent implements OnInit {
) )
} }
@HostListener('keydown.enter') @HostListener('document:keydown.enter')
confirm () { confirm () {
this.confirmService.confirmResponse.next(true) if (this.openedModal) this.openedModal.close()
this.hideModal()
}
@HostListener('keydown.esc')
cancel () {
this.confirmService.confirmResponse.next(false)
this.hideModal()
} }
isConfirmationDisabled () { isConfirmationDisabled () {
@ -70,10 +60,11 @@ export class ConfirmComponent implements OnInit {
showModal () { showModal () {
this.inputValue = '' this.inputValue = ''
this.confirmModal.show()
}
hideModal () { this.openedModal = this.modalService.open(this.confirmModal)
this.confirmModal.hide()
this.openedModal.result
.then(() => this.confirmService.confirmResponse.next(true))
.catch(() => this.confirmService.confirmResponse.next(false))
} }
} }

View File

@ -8,7 +8,6 @@ import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client'
import { LoadingBarRouterModule } from '@ngx-loading-bar/router' import { LoadingBarRouterModule } from '@ngx-loading-bar/router'
import { SimpleNotificationsModule } from 'angular2-notifications' import { SimpleNotificationsModule } from 'angular2-notifications'
import { ModalModule } from 'ngx-bootstrap/modal'
import { AuthService } from './auth' import { AuthService } from './auth'
import { ConfirmComponent, ConfirmService } from './confirm' import { ConfirmComponent, ConfirmService } from './confirm'
@ -23,7 +22,6 @@ import { ServerService } from './server'
FormsModule, FormsModule,
BrowserAnimationsModule, BrowserAnimationsModule,
ModalModule,
SimpleNotificationsModule.forRoot(), SimpleNotificationsModule.forRoot(),
LoadingBarHttpClientModule, LoadingBarHttpClientModule,

View File

@ -50,13 +50,11 @@
</form> </form>
</div> </div>
<div bsModal #forgotPasswordModal="bs-modal" (onShown)="onForgotPasswordModalShown()" class="modal" tabindex="-1"> <!--<ng-template #forgotPasswordModal (onShown)="onForgotPasswordModalShown()">-->
<div class="modal-dialog"> <ng-template #forgotPasswordModal>
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hideForgotPasswordModal()"></span>
<h4 i18n class="modal-title">Forgot your password</h4> <h4 i18n class="modal-title">Forgot your password</h4>
<span class="close" aria-hidden="true" (click)="hideForgotPasswordModal()"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -67,18 +65,14 @@
[(ngModel)]="forgotPasswordEmail" #forgotPasswordEmailInput [(ngModel)]="forgotPasswordEmail" #forgotPasswordEmailInput
> >
</div> </div>
</div>
<div class="form-group inputs"> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="hideForgotPasswordModal()"> <span i18n class="action-button action-button-cancel" (click)="hideForgotPasswordModal()">Cancel</span>
Cancel
</span>
<input <input
type="submit" i18n-value value="Send me an email to reset my password" class="action-button-submit" type="submit" i18n-value value="Send me an email to reset my password" class="action-button-submit"
(click)="askResetPassword()" [disabled]="!forgotPasswordEmailInput.validity.valid" (click)="askResetPassword()" [disabled]="!forgotPasswordEmailInput.validity.valid"
> >
</div> </div>
</div> </ng-template>
</div>
</div>
</div>

View File

@ -2,12 +2,12 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { RedirectService, ServerService } from '@app/core' import { RedirectService, ServerService } from '@app/core'
import { UserService } from '@app/shared' import { UserService } from '@app/shared'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { AuthService } from '../core' import { AuthService } from '../core'
import { FormReactive } from '../shared' import { FormReactive } from '../shared'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service' import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-validators.service'
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'my-login', selector: 'my-login',
@ -16,14 +16,17 @@ import { LoginValidatorsService } from '@app/shared/forms/form-validators/login-
}) })
export class LoginComponent extends FormReactive implements OnInit { export class LoginComponent extends FormReactive implements OnInit {
@ViewChild('forgotPasswordModal') forgotPasswordModal: ModalDirective @ViewChild('forgotPasswordModal') forgotPasswordModal: ElementRef
@ViewChild('forgotPasswordEmailInput') forgotPasswordEmailInput: ElementRef @ViewChild('forgotPasswordEmailInput') forgotPasswordEmailInput: ElementRef
error: string = null error: string = null
forgotPasswordEmail = '' forgotPasswordEmail = ''
private openedForgotPasswordModal: NgbModalRef
constructor ( constructor (
protected formValidatorService: FormValidatorService, protected formValidatorService: FormValidatorService,
private modalService: NgbModal,
private loginValidatorsService: LoginValidatorsService, private loginValidatorsService: LoginValidatorsService,
private authService: AuthService, private authService: AuthService,
private userService: UserService, private userService: UserService,
@ -84,10 +87,10 @@ export class LoginComponent extends FormReactive implements OnInit {
} }
openForgotPasswordModal () { openForgotPasswordModal () {
this.forgotPasswordModal.show() this.openedForgotPasswordModal = this.modalService.open(this.forgotPasswordModal)
} }
hideForgotPasswordModal () { hideForgotPasswordModal () {
this.forgotPasswordModal.hide() this.openedForgotPasswordModal.close()
} }
} }

View File

@ -1,15 +1,10 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <ng-template #modal let-hide="close">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hide()"></span>
<h4 i18n class="modal-title">Change the language</h4> <h4 i18n class="modal-title">Change the language</h4>
<span class="close" aria-label="Close" role="button" (click)="hide()"></span>
</div> </div>
<div class="modal-body" *ngFor="let lang of languages"> <div class="modal-body">
<a [href]="buildLanguageLink(lang)">{{ lang.label }}</a> <a *ngFor="let lang of languages" [href]="buildLanguageLink(lang)">{{ lang.label }}</a>
</div> </div>
</div> </ng-template>
</div>
</div>

View File

@ -1,19 +1,12 @@
@import '_variables'; @import '_variables';
@import '_mixins'; @import '_mixins';
.modal {
z-index: 10005;
}
.modal-title {
text-align: center;
}
.modal-body { .modal-body {
text-align: center; text-align: center;
a { a {
display: block;
font-size: 16px; font-size: 16px;
margin-top: 10px; margin: 15px;
} }
} }

View File

@ -1,6 +1,6 @@
import { Component, ViewChild } from '@angular/core' import { Component, ElementRef, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { I18N_LOCALES } from '../../../../shared' import { I18N_LOCALES } from '../../../../shared'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'my-language-chooser', selector: 'my-language-chooser',
@ -8,21 +8,17 @@ import { I18N_LOCALES } from '../../../../shared'
styleUrls: [ './language-chooser.component.scss' ] styleUrls: [ './language-chooser.component.scss' ]
}) })
export class LanguageChooserComponent { 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) this.languages = Object.keys(I18N_LOCALES)
.map(k => ({ id: k, label: I18N_LOCALES[k] })) .map(k => ({ id: k, label: I18N_LOCALES[k] }))
} }
show () { show () {
this.modal.show() this.modalService.open(this.modal)
}
hide () {
this.modal.hide()
} }
buildLanguageLink (lang: { id: string }) { buildLanguageLink (lang: { id: string }) {

View File

@ -11,24 +11,22 @@
<div class="logged-in-email">{{ user.username }}</div> <div class="logged-in-email">{{ user.username }}</div>
</div> </div>
<div class="logged-in-more" dropdown placement="right" container="body"> <div class="logged-in-more" ngbDropdown placement="bottom-right">
<span class="glyphicon glyphicon-option-vertical" dropdownToggle></span> <span class="glyphicon glyphicon-option-vertical" ngbDropdownToggle role="button"></span>
<ul *dropdownMenu class="dropdown-menu"> <div ngbDropdownMenu>
<li> <a *ngIf="user.account" i18n [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="dropdown-item">
<a i18n [routerLink]="[ '/accounts', user.account?.nameWithHost ]" class="dropdown-item" title="My public profile">
My public profile My public profile
</a> </a>
<a i18n routerLink="/my-account" class="dropdown-item" title="My account"> <a i18n routerLink="/my-account" class="dropdown-item">
My account My account
</a> </a>
<a i18n (click)="logout($event)" class="dropdown-item" title="Log out" href="#"> <a i18n (click)="logout($event)" class="dropdown-item" href="#">
Log out Log out
</a> </a>
</li> </div>
</ul>
</div> </div>
</div> </div>

View File

@ -69,6 +69,10 @@ menu {
.glyphicon { .glyphicon {
cursor: pointer; cursor: pointer;
font-size: 18px; font-size: 18px;
&::after {
border: none;
}
} }
} }
} }

View File

@ -17,7 +17,7 @@
</div> </div>
</div> </div>
<div class="results-filter" [collapse]="isSearchFilterCollapsed"> <div class="results-filter" [ngbCollapse]="isSearchFilterCollapsed">
<my-search-filters [advancedSearch]="advancedSearch" (filtered)="onFiltered()"></my-search-filters> <my-search-filters [advancedSearch]="advancedSearch" (filtered)="onFiltered()"></my-search-filters>
</div> </div>
</div> </div>

View File

@ -4,14 +4,14 @@ import { SearchComponent } from '@app/search/search.component'
import { SearchService } from '@app/search/search.service' import { SearchService } from '@app/search/search.service'
import { SearchRoutingModule } from '@app/search/search-routing.module' import { SearchRoutingModule } from '@app/search/search-routing.module'
import { SearchFiltersComponent } from '@app/search/search-filters.component' import { SearchFiltersComponent } from '@app/search/search-filters.component'
import { CollapseModule } from 'ngx-bootstrap/collapse' import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'
@NgModule({ @NgModule({
imports: [ imports: [
SearchRoutingModule, SearchRoutingModule,
SharedModule, SharedModule,
CollapseModule.forRoot() NgbCollapseModule.forRoot()
], ],
declarations: [ declarations: [

View File

@ -5,8 +5,13 @@
id="description" name="description"> id="description" name="description">
</textarea> </textarea>
<tabset *ngIf="arePreviewsDisplayed()" class="previews"> <ngb-tabset *ngIf="arePreviewsDisplayed()" class="previews" type="pills">
<tab *ngIf="truncate !== undefined" i18n-heading heading="Truncated preview" [innerHTML]="truncatedPreviewHTML"></tab> <ngb-tab *ngIf="truncate !== undefined" i18n-title title="Truncated preview">
<tab i18n-heading heading="Complete preview" [innerHTML]="previewHTML"></tab> <ng-template ngbTabContent><div [innerHTML]="truncatedPreviewHTML"></div></ng-template>
</tabset> </ngb-tab>
<ngb-tab i18n-title title="Complete preview">
<ng-template ngbTabContent><div [innerHTML]="previewHTML"></div></ng-template>
</ngb-tab>
</ngb-tabset>
</div> </div>

View File

@ -18,9 +18,8 @@
title="Get help" title="Get help"
i18n-title i18n-title
[attr.aria-pressed]="isPopoverOpened" [attr.aria-pressed]="isPopoverOpened"
[popover]="tooltipTemplate" [ngbPopover]="tooltipTemplate"
[placement]="tooltipPlacement" [placement]="tooltipPlacement"
[outsideClick]="true"
(onHidden)="onPopoverHidden()" (onHidden)="onPopoverHidden()"
(onShown)="onPopoverShown()" (onShown)="onPopoverShown()"
></span> ></span>

View File

@ -8,11 +8,6 @@ import { HelpComponent } from '@app/shared/misc/help.component'
import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
import { MarkdownService } from '@app/videos/shared' 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 { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared' 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 { PeertubeCheckboxComponent } from '@app/shared/forms/peertube-checkbox.component'
import { VideoImportService } from '@app/shared/video-import/video-import.service' import { VideoImportService } from '@app/shared/video-import/video-import.service'
import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component' import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component'
import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
@NgModule({ @NgModule({
imports: [ imports: [
@ -62,11 +58,11 @@ import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.com
RouterModule, RouterModule,
HttpClientModule, HttpClientModule,
BsDropdownModule.forRoot(), NgbDropdownModule.forRoot(),
ModalModule.forRoot(), NgbModalModule.forRoot(),
PopoverModule.forRoot(), NgbPopoverModule.forRoot(),
TabsModule.forRoot(), NgbTabsetModule.forRoot(),
TooltipModule.forRoot(), NgbTooltipModule.forRoot(),
PrimeSharedModule, PrimeSharedModule,
NgPipesModule NgPipesModule
@ -97,11 +93,12 @@ import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.com
RouterModule, RouterModule,
HttpClientModule, HttpClientModule,
BsDropdownModule, NgbDropdownModule,
ModalModule, NgbModalModule,
PopoverModule, NgbPopoverModule,
TabsModule, NgbTabsetModule,
TooltipModule, NgbTooltipModule,
PrimeSharedModule, PrimeSharedModule,
BytesPipe, BytesPipe,
KeysPipe, KeysPipe,

View File

@ -1,13 +1,10 @@
<div class="video-feed"> <div class="video-feed">
<span *ngIf="syndicationItems.length !== 0" class="icon icon-syndication" <span
[popover]="feedsList" *ngIf="syndicationItems.length !== 0" [ngbPopover]="feedsList" placement="bottom"
placement="bottom" class="icon icon-syndication" role="button"
[outsideClick]="true"> ></span>
</span>
<ng-template #feedsList> <ng-template #feedsList>
<div *ngFor="let item of syndicationItems"> <a *ngFor="let item of syndicationItems" [href]="item.url" target="_blank" rel="noopener noreferrer">{{ item.label }}</a>
<a [href]="item.url" target="_blank" rel="noopener noreferrer">{{ item.label }}</a>
</div>
</ng-template> </ng-template>
</div> </div>

View File

@ -5,6 +5,7 @@
@include disable-default-a-behaviour; @include disable-default-a-behaviour;
color: black; color: black;
display: block;
} }
.icon { .icon {

View File

@ -1,10 +1,9 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <ng-template #modal>
<div class="modal-dialog"> <ng-container [formGroup]="form">
<div class="modal-content" [formGroup]="form">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hide()"></span>
<h4 i18n class="modal-title">Add caption</h4> <h4 i18n class="modal-title">Add caption</h4>
<span class="close" aria-label="Close" role="button" (click)="hide()"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -30,8 +29,9 @@
<div *ngIf="isReplacingExistingCaption()" class="warning-replace-caption" i18n> <div *ngIf="isReplacingExistingCaption()" class="warning-replace-caption" i18n>
This will replace an existing caption! This will replace an existing caption!
</div> </div>
</div>
<div class="form-group inputs"> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()"> <span i18n class="action-button action-button-cancel" (click)="hide()">
Cancel Cancel
</span> </span>
@ -41,7 +41,5 @@
[disabled]="!form.valid" (click)="addCaption()" [disabled]="!form.valid" (click)="addCaption()"
> >
</div> </div>
</div> </ng-container>
</div> </ng-template>
</div>
</div>

View File

@ -1,10 +1,10 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { FormReactive } from '@app/shared' import { FormReactive } from '@app/shared'
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validators/video-captions-validators.service' import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validators/video-captions-validators.service'
import { ServerService } from '@app/core' import { ServerService } from '@app/core'
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'my-video-caption-add-modal', selector: 'my-video-caption-add-modal',
@ -17,14 +17,16 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
@Output() captionAdded = new EventEmitter<VideoCaptionEdit>() @Output() captionAdded = new EventEmitter<VideoCaptionEdit>()
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: ElementRef
videoCaptionLanguages = [] videoCaptionLanguages = []
private openedModal: NgbModalRef
private closingModal = false private closingModal = false
constructor ( constructor (
protected formValidatorService: FormValidatorService, protected formValidatorService: FormValidatorService,
private modalService: NgbModal,
private serverService: ServerService, private serverService: ServerService,
private videoCaptionsValidatorsService: VideoCaptionsValidatorsService private videoCaptionsValidatorsService: VideoCaptionsValidatorsService
) { ) {
@ -51,13 +53,12 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
show () { show () {
this.closingModal = false this.closingModal = false
this.modal.show() this.openedModal = this.modalService.open(this.modal, { keyboard: false })
} }
hide () { hide () {
this.closingModal = true this.closingModal = true
this.openedModal.close()
this.modal.hide()
} }
isReplacingExistingCaption () { isReplacingExistingCaption () {

View File

@ -1,7 +1,9 @@
<div class="video-edit row" [formGroup]="form"> <div class="video-edit" [formGroup]="form">
<tabset class="root-tabset bootstrap"> <ngb-tabset class="root-tabset bootstrap">
<tab i18n-heading heading="Basic info"> <ngb-tab i18n-title title="Basic info">
<ng-template ngbTabContent>
<div class="row">
<div class="col-md-8"> <div class="col-md-8">
<div class="form-group"> <div class="form-group">
<label i18n for="name">Title</label> <label i18n for="name">Title</label>
@ -128,10 +130,13 @@
></my-peertube-checkbox> ></my-peertube-checkbox>
</div> </div>
</tab> </div>
</ng-template>
</ngb-tab>
<tab i18n-heading heading="Captions"> <ngb-tab i18n-title title="Captions">
<div class="col-md-12 captions"> <ng-template ngbTabContent>
<div class="captions">
<div class="captions-header"> <div class="captions-header">
<a (click)="openAddCaptionModal()" class="create-caption"> <a (click)="openAddCaptionModal()" class="create-caption">
@ -177,10 +182,12 @@
</div> </div>
</div> </div>
</tab> </ng-template>
</ngb-tab>
<tab i18n-heading heading="Advanced settings"> <ngb-tab i18n-title title="Advanced settings">
<div class="col-md-12 advanced-settings"> <ng-template ngbTabContent>
<div class="advanced-settings">
<div class="form-group"> <div class="form-group">
<my-video-image <my-video-image
i18n-inputLabel inputLabel="Upload thumbnail" inputName="thumbnailfile" formControlName="thumbnailfile" i18n-inputLabel inputLabel="Upload thumbnail" inputName="thumbnailfile" formControlName="thumbnailfile"
@ -207,9 +214,10 @@
</div> </div>
</div> </div>
</div> </div>
</tab> </ng-template>
</ngb-tab>
</tabset> </ngb-tabset>
</div> </div>

View File

@ -111,6 +111,8 @@
border: none; border: none;
padding: 0; padding: 0;
outline: 0; outline: 0;
color: inherit;
font-weight: $font-semibold;
} }
.icon.icon-validate { .icon.icon-validate {
@ -143,15 +145,7 @@ p-calendar {
/deep/ { /deep/ {
.root-tabset > .nav { .root-tabset > .nav {
margin-left: 15px;
margin-bottom: 15px; margin-bottom: 15px;
.nav-link {
display: flex !important;
align-items: center;
height: 30px !important;
padding: 0 15px !important;
}
} }
.ng2-tag-input { .ng2-tag-input {

View File

@ -1,5 +1,4 @@
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { TabsModule } from 'ngx-bootstrap/tabs'
import { TagInputModule } from 'ngx-chips' import { TagInputModule } from 'ngx-chips'
import { SharedModule } from '../../../shared/' import { SharedModule } from '../../../shared/'
import { VideoEditComponent } from './video-edit.component' import { VideoEditComponent } from './video-edit.component'
@ -23,7 +22,6 @@ import { VideoCaptionAddModalComponent } from './video-caption-add-modal.compone
exports: [ exports: [
TagInputModule, TagInputModule,
TabsModule,
CalendarModule, CalendarModule,
VideoEditComponent VideoEditComponent

View File

@ -1,10 +1,7 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <ng-template #modal let-hide="close">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hide()"></span>
<h4 i18n class="modal-title">Download video</h4> <h4 i18n class="modal-title">Download video</h4>
<span class="close" aria-hidden="true" (click)="hide()"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -30,8 +27,9 @@
<label i18n for="download-magnet">Torrent (magnet link)</label> <label i18n for="download-magnet">Torrent (magnet link)</label>
</div> </div>
</div> </div>
</div>
<div class="form-group inputs"> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()"> <span i18n class="action-button action-button-cancel" (click)="hide()">
Cancel Cancel
</span> </span>
@ -41,7 +39,4 @@
(click)="download()" (click)="download()"
> >
</div> </div>
</div> </ng-template>
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
import { Component, Input, OnInit, ViewChild } from '@angular/core' import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { VideoDetails } from '../../../shared/video/video-details.model' import { VideoDetails } from '../../../shared/video/video-details.model'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'my-video-download', selector: 'my-video-download',
@ -10,12 +10,12 @@ import { VideoDetails } from '../../../shared/video/video-details.model'
export class VideoDownloadComponent implements OnInit { export class VideoDownloadComponent implements OnInit {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: ElementRef
downloadType: 'direct' | 'torrent' | 'magnet' = 'torrent' downloadType: 'direct' | 'torrent' | 'magnet' = 'torrent'
resolutionId: number | string = -1 resolutionId: number | string = -1
constructor () { constructor (private modalService: NgbModal) {
// empty // empty
} }
@ -24,11 +24,7 @@ export class VideoDownloadComponent implements OnInit {
} }
show () { show () {
this.modal.show() this.modalService.open(this.modal)
}
hide () {
this.modal.hide()
} }
download () { download () {

View File

@ -1,10 +1,7 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <ng-template #modal>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hide()"></span>
<h4 i18n class="modal-title">Report video</h4> <h4 i18n class="modal-title">Report video</h4>
<span class="close" aria-label="Close" role="button" (click)="hide()"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -31,6 +28,4 @@
</form> </form>
</div> </div>
</div> </ng-template>
</div>
</div>

View File

@ -1,11 +1,12 @@
import { Component, Input, OnInit, ViewChild } from '@angular/core' import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { FormReactive, VideoAbuseService } from '../../../shared/index' import { FormReactive, VideoAbuseService } from '../../../shared/index'
import { VideoDetails } from '../../../shared/video/video-details.model' import { VideoDetails } from '../../../shared/video/video-details.model'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/video-abuse-validators.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({ @Component({
selector: 'my-video-report', selector: 'my-video-report',
@ -15,12 +16,15 @@ import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/v
export class VideoReportComponent extends FormReactive implements OnInit { export class VideoReportComponent extends FormReactive implements OnInit {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: NgbModal
error: string = null error: string = null
private openedModal: NgbModalRef
constructor ( constructor (
protected formValidatorService: FormValidatorService, protected formValidatorService: FormValidatorService,
private modalService: NgbModal,
private videoAbuseValidatorsService: VideoAbuseValidatorsService, private videoAbuseValidatorsService: VideoAbuseValidatorsService,
private videoAbuseService: VideoAbuseService, private videoAbuseService: VideoAbuseService,
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
@ -36,11 +40,12 @@ export class VideoReportComponent extends FormReactive implements OnInit {
} }
show () { show () {
this.modal.show() this.openedModal = this.modalService.open(this.modal, { keyboard: false })
} }
hide () { hide () {
this.modal.hide() this.openedModal.close()
this.openedModal = null
} }
report () { report () {

View File

@ -1,10 +1,7 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <ng-template #modal let-hide="close">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hide()"></span>
<h4 i18n class="modal-title">Share</h4> <h4 i18n class="modal-title">Share</h4>
<span class="close" aria-hidden="true" (click)="hide()"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -12,8 +9,8 @@
<label i18n>URL</label> <label i18n>URL</label>
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoUrl()" /> <input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoUrl()" />
<div class="input-group-btn" placement="bottom right"> <div class="input-group-append">
<button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-default btn-search"> <button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-copy"></span> <span class="glyphicon glyphicon-copy"></span>
</button> </button>
</div> </div>
@ -24,8 +21,8 @@
<label i18n>Embed</label> <label i18n>Embed</label>
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<input #shareInput (click)="shareInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoIframeCode()" /> <input #shareInput (click)="shareInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getVideoIframeCode()" />
<div class="input-group-btn" placement="bottom right"> <div class="input-group-append">
<button [ngxClipboard]="shareInput" (click)="activateCopiedMessage()" type="button" class="btn btn-default btn-search"> <button [ngxClipboard]="shareInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-copy"></span> <span class="glyphicon glyphicon-copy"></span>
</button> </button>
</div> </div>
@ -40,13 +37,10 @@
<label i18n>QR-Code</label> <label i18n>QR-Code</label>
<ngx-qrcode qrc-element-type="url" [qrc-value]="getVideoUrl()" qrc-errorCorrectionLevel="Q"></ngx-qrcode> <ngx-qrcode qrc-element-type="url" [qrc-value]="getVideoUrl()" qrc-errorCorrectionLevel="Q"></ngx-qrcode>
</div> </div>
</div>
<div class="form-group inputs"> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()"> <span i18n class="action-button action-button-cancel" (click)="hide()">Cancel</span>
Cancel
</span>
</div> </div>
</div>
</div> </ng-template>
</div>
</div>

View File

@ -1,7 +1,14 @@
@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
.action-button-cancel { .action-button-cancel {
margin-right: 0 !important; margin-right: 0 !important;
} }
.btn-outline-secondary {
border-color: $input-border-color;
}
.qr-code-group { .qr-code-group {
text-align: center; text-align: center;
} }

View 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 { NotificationsService } from 'angular2-notifications'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { VideoDetails } from '../../../shared/video/video-details.model' import { VideoDetails } from '../../../shared/video/video-details.model'
import { buildVideoEmbed } from '../../../../assets/player/utils' import { buildVideoEmbed } from '../../../../assets/player/utils'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'my-video-share', selector: 'my-video-share',
@ -15,9 +13,10 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
export class VideoShareComponent { export class VideoShareComponent {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: ElementRef
constructor ( constructor (
private modalService: NgbModal,
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
private i18n: I18n private i18n: I18n
) { ) {
@ -25,11 +24,7 @@ export class VideoShareComponent {
} }
show () { show () {
this.modal.show() this.modalService.open(this.modal)
}
hide () {
this.modal.hide()
} }
getVideoIframeCode () { getVideoIframeCode () {

View File

@ -1,22 +1,12 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <ng-template #modal let-hide="close">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<span class="close" aria-hidden="true" (click)="hide()"></span>
<h4 i18n class="modal-title">Support</h4> <h4 i18n class="modal-title">Support</h4>
<span class="close" aria-label="Close" role="button" (click)="hide()"></span>
</div> </div>
<div class="modal-body"> <div class="modal-body" [innerHTML]="videoHTMLSupport"></div>
<div [innerHTML]="videoHTMLSupport"></div> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()">Cancel</span>
<div class="form-group inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()">
Cancel
</span>
</div> </div>
</div> </ng-template>
</div>
</div>
</div>

View File

@ -1,8 +1,8 @@
import { Component, Input, ViewChild } from '@angular/core' import { Component, Input, ViewChild } from '@angular/core'
import { MarkdownService } from '@app/videos/shared' import { MarkdownService } from '@app/videos/shared'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { VideoDetails } from '../../../shared/video/video-details.model' import { VideoDetails } from '../../../shared/video/video-details.model'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'my-video-support', selector: 'my-video-support',
@ -12,21 +12,19 @@ import { VideoDetails } from '../../../shared/video/video-details.model'
export class VideoSupportComponent { export class VideoSupportComponent {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: NgbModal
videoHTMLSupport = '' videoHTMLSupport = ''
constructor (private markdownService: MarkdownService) { constructor (
private markdownService: MarkdownService,
private modalService: NgbModal
) {
// empty // empty
} }
show () { show () {
this.modal.show()
this.videoHTMLSupport = this.markdownService.enhancedMarkdownToHTML(this.video.support) this.videoHTMLSupport = this.markdownService.enhancedMarkdownToHTML(this.video.support)
} this.modalService.open(this.modal)
hide () {
this.modal.hide()
} }
} }

View File

@ -76,48 +76,38 @@
<span class="icon-text" i18n>Share</span> <span class="icon-text" i18n>Share</span>
</div> </div>
<div class="action-more" dropdown dropup="true" placement="right" role="button"> <div class="action-more" ngbDropdown placement="top" role="button">
<div class="action-button" dropdownToggle> <div class="action-button" ngbDropdownToggle role="button">
<span class="icon icon-more"></span> <span class="icon icon-more"></span>
</div> </div>
<ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button"> <div ngbDropdownMenu>
<li role="menuitem">
<a class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)"> <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> <span class="icon icon-download"></span> <ng-container i18n>Download</ng-container>
</a> </a>
</li>
<li *ngIf="isUserLoggedIn()" role="menuitem"> <a *ngIf="isUserLoggedIn()" class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)">
<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> <span class="icon icon-alert"></span> <ng-container i18n>Report</ng-container>
</a> </a>
</li>
<li *ngIf="isVideoBlacklistable()" role="menuitem"> <a *ngIf="isVideoBlacklistable()" class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="blacklistVideo($event)">
<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> <span class="icon icon-blacklist"></span> <ng-container i18n>Blacklist</ng-container>
</a> </a>
</li>
<li *ngIf="isVideoUpdatable()" role="menuitem"> <a *ngIf="isVideoUpdatable()" class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]">
<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> <span class="icon icon-edit"></span> <ng-container i18n>Update</ng-container>
</a> </a>
</li>
<li *ngIf="isVideoRemovable()" role="menuitem"> <a *ngIf="isVideoRemovable()" class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)">
<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> <span class="icon icon-blacklist"></span> <ng-container i18n>Delete</ng-container>
</a> </a>
</li> </div>
</ul>
</div> </div>
</div> </div>
<div <div
class="video-info-likes-dislikes-bar" 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 class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div>
</div> </div>
</div> </div>

View File

@ -177,6 +177,10 @@
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
white-space: nowrap; white-space: nowrap;
&::after {
display: none;
}
.icon { .icon {
@include icon(21px); @include icon(21px);

View File

@ -1,7 +1,6 @@
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { LinkifierService } from '@app/videos/+video-watch/comment/linkifier.service' import { LinkifierService } from '@app/videos/+video-watch/comment/linkifier.service'
import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component' import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-support.component'
import { TooltipModule } from 'ngx-bootstrap/tooltip'
import { ClipboardModule } from 'ngx-clipboard' import { ClipboardModule } from 'ngx-clipboard'
import { SharedModule } from '../../shared' import { SharedModule } from '../../shared'
import { MarkdownService } 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 { VideoDownloadComponent } from './modal/video-download.component'
import { VideoReportComponent } from './modal/video-report.component' import { VideoReportComponent } from './modal/video-report.component'
import { VideoShareComponent } from './modal/video-share.component' import { VideoShareComponent } from './modal/video-share.component'
import { VideoWatchRoutingModule } from './video-watch-routing.module' import { VideoWatchRoutingModule } from './video-watch-routing.module'
import { VideoWatchComponent } from './video-watch.component' import { VideoWatchComponent } from './video-watch.component'
import { NgxQRCodeModule } from 'ngx-qrcode2' import { NgxQRCodeModule } from 'ngx-qrcode2'
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
@NgModule({ @NgModule({
imports: [ imports: [
VideoWatchRoutingModule, VideoWatchRoutingModule,
SharedModule, SharedModule,
ClipboardModule, ClipboardModule,
TooltipModule.forRoot(), NgbTooltipModule.forRoot(),
NgxQRCodeModule NgxQRCodeModule
], ],

View File

@ -42,6 +42,10 @@ input.readonly {
background-color: #fff !important; background-color: #fff !important;
} }
input, textarea {
outline: none;
}
label { label {
font-weight: $font-bold; font-weight: $font-bold;
font-size: 15px; font-size: 15px;
@ -174,9 +178,13 @@ label {
@include icon(24px); @include icon(24px);
position: relative; position: relative;
right: -1px; top: 3px;
float: right; float: right;
background-image: url('../assets/images/global/cross.svg'); background-image: url('../assets/images/global/cross.svg');
margin: 0;
padding: 0;
opacity: 1;
} }
} }
@ -200,47 +208,35 @@ label {
} }
} }
tabset:not(.bootstrap) { // Nav customizations
.nav { .nav .nav-link {
font-size: 16px !important;
border: none !important;
.nav-item .nav-link {
margin-right: 30px;
padding: 0;
border-radius: 3px;
border: none !important;
.tab-link {
display: flex !important; display: flex !important;
align-items: center; align-items: center;
min-height: 30px !important; height: 30px !important;
padding: 0 15px; padding: 10px 15px !important;
} }
&, & a { .nav.nav-pills {
color: #000 !important; font-size: 16px !important;
@include disable-default-a-behaviour;
}
&.active, &:hover { .nav-link.active {
background-color: #F0F0F0;
}
&.active {
font-weight: $font-semibold !important; font-weight: $font-semibold !important;
} }
}
a {
@include disable-default-a-behaviour;
color: #000;
} }
} }
tabset.bootstrap { ngb-tabset.bootstrap {
margin-left: 0;
.nav-item .nav-link { .nav-link {
&, & a { &, & a {
color: #000;
@include disable-default-a-behaviour; @include disable-default-a-behaviour;
color: #000 !important;
} }
} }
} }

View File

@ -1,37 +1,51 @@
@import "~bootstrap/scss/functions"; $dropdown-link-active-bg: inherit;
@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"; $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';

View File

@ -191,6 +191,10 @@
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@neos21/bootstrap3-glyphicons/-/bootstrap3-glyphicons-1.0.1.tgz#e5eeec43e0153d4b51effd9ecb58cdf7029924d7" 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": "@ngtools/webpack@6.1.1":
version "6.1.1" version "6.1.1"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-6.1.1.tgz#dcfea287c0c1358f3e123621c65b0e3ccaab5b70" resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-6.1.1.tgz#dcfea287c0c1358f3e123621c65b0e3ccaab5b70"
@ -5350,10 +5354,6 @@ ng2-material-dropdown@0.10.1:
dependencies: dependencies:
tslib "^1.9.0" 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: ngx-chips@1.9.3:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/ngx-chips/-/ngx-chips-1.9.3.tgz#0ebc13b4868d9cd480478ed93fd56bcc3b68ea66" resolved "https://registry.yarnpkg.com/ngx-chips/-/ngx-chips-1.9.3.tgz#0ebc13b4868d9cd480478ed93fd56bcc3b68ea66"