<my-welcome-modal #welcomeModal></my-welcome-modal>
<my-instance-config-warning-modal #instanceConfigWarningModal></my-instance-config-warning-modal>
</ng-template>
+
+<my-custom-modal #customModal></my-custom-modal>
-import { Component, OnInit, ViewChild } from '@angular/core'
+import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
import { Event, GuardsCheckStart, NavigationEnd, Router, Scroll } from '@angular/router'
import { AuthService, RedirectService, ServerService, ThemeService } from '@app/core'
import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants'
import { WelcomeModalComponent } from '@app/modal/welcome-modal.component'
import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component'
+import { CustomModalComponent } from '@app/modal/custom-modal.component'
import { ServerConfig, UserRole } from '@shared/models'
import { User } from '@app/shared'
import { InstanceService } from '@app/shared/instance/instance.service'
templateUrl: './app.component.html',
styleUrls: [ './app.component.scss' ]
})
-export class AppComponent implements OnInit {
+export class AppComponent implements OnInit, AfterViewInit {
@ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent
@ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent
+ @ViewChild('customModal') customModal: CustomModalComponent
customCSS: SafeHtml
this.openModalsIfNeeded()
}
+ ngAfterViewInit () {
+ this.pluginService.initializeCustomModal(this.customModal)
+ }
+
isUserLoggedIn () {
return this.authService.isLoggedIn()
}
import { buildFileLocale, getCompleteLocale, isDefaultLocale } from '@shared/models'
import { APP_BASE_HREF } from '@angular/common'
import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component'
+import { CustomModalComponent } from '@app/modal/custom-modal.component'
export function metaFactory (serverService: ServerService): MetaLoader {
return new MetaStaticLoader({
SuggestionsComponent,
SuggestionComponent,
+ CustomModalComponent,
WelcomeModalComponent,
InstanceConfigWarningModalComponent
],
import { RegisterClientHelpers } from '../../../types/register-client-option.model'
import { PluginTranslation } from '@shared/models/plugins/plugin-translation.model'
import { importModule } from '@app/shared/misc/utils'
+import { CustomModalComponent } from '@app/modal/custom-modal.component'
interface HookStructValue extends RegisterClientHookOptions {
plugin: ServerConfigPlugin
translationsObservable: Observable<PluginTranslation>
+ customModal: CustomModalComponent
+
private plugins: ServerConfigPlugin[] = []
private scopes: { [ scopeName: string ]: PluginInfo[] } = {}
private loadedScripts: { [ script: string ]: boolean } = {}
})
}
+ initializeCustomModal (customModal: CustomModalComponent) {
+ this.customModal = customModal
+ }
+
ensurePluginsAreBuilt () {
return this.pluginsBuilt.asObservable()
.pipe(first(), shareReplay())
success: (text: string, title?: string, timeout?: number) => this.notifier.success(text, title, timeout)
},
+ showModal: (input: {
+ title: string,
+ content: string,
+ close?: boolean,
+ cancel?: { value: string, action?: () => void },
+ confirm?: { value: string, action?: () => void }
+ }) => {
+ this.customModal.show(input)
+ },
+
translate: (value: string) => {
return this.translationsObservable
.pipe(map(allTranslations => allTranslations[npmName]))
--- /dev/null
+<ng-template #modal let-hide="close">
+ <div class="modal-header">
+ <h4 class="modal-title">{{title}}</h4>
+ <my-global-icon *ngIf="close" iconName="cross" aria-label="Close" role="button" (click)="onCloseClick()"></my-global-icon>
+ </div>
+
+ <div class="modal-body" [innerHTML]="content"></div>
+
+ <div *ngIf="hasCancel() || hasConfirm()" class="modal-footer inputs">
+ <input
+ *ngIf="hasCancel()" type="button" role="button" value="{{cancel.value}}" class="action-button action-button-cancel"
+ (click)="onCancelClick()" (key.enter)="onCancelClick()"
+ >
+
+ <input
+ *ngIf="hasConfirm()" type="button" role="button" value="{{confirm.value}}" class="action-button action-button-confirm"
+ (click)="onConfirmClick()" (key.enter)="onConfirmClick()"
+ >
+ </div>
+</ng-template>
--- /dev/null
+@import '_mixins';
+@import '_variables';
+
+.modal-body {
+ font-size: 15px;
+}
+
+li {
+ margin-bottom: 10px;
+}
+
+.action-button-cancel {
+ @include peertube-button;
+ @include grey-button;
+}
+
+.action-button-confirm {
+ @include peertube-button;
+ @include orange-button;
+}
--- /dev/null
+import { Component, ElementRef, ViewChild, Input } from '@angular/core'
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
+
+@Component({
+ selector: 'my-custom-modal',
+ templateUrl: './custom-modal.component.html',
+ styleUrls: [ './custom-modal.component.scss' ]
+})
+export class CustomModalComponent {
+ @ViewChild('modal', { static: true }) modal: ElementRef
+
+ @Input() title: string
+ @Input() content: string
+ @Input() close?: boolean
+ @Input() cancel?: { value: string, action?: () => void }
+ @Input() confirm?: { value: string, action?: () => void }
+
+ private modalRef: NgbModalRef
+
+ constructor (
+ private modalService: NgbModal
+ ) { }
+
+ show (input: {
+ title: string,
+ content: string,
+ close?: boolean,
+ cancel?: { value: string, action?: () => void },
+ confirm?: { value: string, action?: () => void }
+ }) {
+ if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) {
+ console.error('Cannot open another custom modal, one is already opened.')
+ return
+ }
+
+ const { title, content, close, cancel, confirm } = input
+
+ this.title = title
+ this.content = content
+ this.close = close
+ this.cancel = cancel
+ this.confirm = confirm
+
+ this.modalRef = this.modalService.open(this.modal, {
+ centered: true,
+ backdrop: 'static',
+ keyboard: false,
+ size: 'lg'
+ })
+ }
+
+ onCancelClick () {
+ this.modalRef.close()
+
+ if (typeof this.cancel.action === 'function') {
+ this.cancel.action()
+ }
+
+ this.destroy()
+ }
+
+ onCloseClick () {
+ this.modalRef.close()
+ this.destroy()
+ }
+
+ onConfirmClick () {
+ this.modalRef.close()
+
+ if (typeof this.confirm.action === 'function') {
+ this.confirm.action()
+ }
+
+ this.destroy()
+ }
+
+ hasCancel () {
+ return typeof this.cancel !== 'undefined'
+ }
+
+ hasConfirm () {
+ return typeof this.confirm !== 'undefined'
+ }
+
+ private destroy () {
+ delete this.modalRef
+ delete this.title
+ delete this.content
+ delete this.close
+ delete this.cancel
+ delete this.confirm
+ }
+}
success: (text: string, title?: string, timeout?: number) => void
}
+ showModal: (input: {
+ title: string,
+ content: string,
+ close?: boolean,
+ cancel?: { value: string, action?: () => void },
+ confirm?: { value: string, action?: () => void }
+ }) => void
+
translate: (toTranslate: string) => Promise<string>
}
notifier.error('Error message content.')
```
+#### Custom Modal
+
+To show a custom modal:
+
+```js
+ peertubeHelpers.showModal({
+ title: 'My custom modal title',
+ content: '<p>My custom modal content</p>',
+ // Optionals parameters :
+ // show close icon
+ close: true,
+ // show cancel button and call action() after hiding modal
+ cancel: { value: 'cancel', action: () => {} },
+ // show confirm button and call action() after hiding modal
+ confirm: { value: 'confirm', action: () => {} },
+ })
+```
+
#### Translate
You can translate some strings of your plugin (PeerTube will use your `translations` object of your `package.json` file):