mirror of https://github.com/Chocobozzz/PeerTube
Add custom modal to plugin helpers (#2631)
* Add custom modal component * Add custom modal to app and plugins helpers * Fixes custom modal component * Add doc for custom modal * Fix newline end of file html and scss files * Move my-custom-modal component outside component for UserLoggedIn modals * Move initializeCustomModal to ngAfterViewInit() * Wrap events and conditionnals * Replace ng-show with ngIf* * Add modalRef to open only one modal + onCloseClick * Refacto + Fix access methods of custom modal * Fix methods names custom-modal.component * Fix implement AfterViewInit & no default boolean Co-authored-by: kimsible <kimsible@users.noreply.github.com>pull/2654/head
parent
45c14ae1b2
commit
437e8e06eb
|
@ -54,3 +54,5 @@
|
|||
<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>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
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'
|
||||
|
@ -14,6 +14,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
|||
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'
|
||||
|
@ -24,9 +25,10 @@ import { MenuService } from './core/menu/menu.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
|
||||
|
||||
|
@ -87,6 +89,10 @@ export class AppComponent implements OnInit {
|
|||
this.openModalsIfNeeded()
|
||||
}
|
||||
|
||||
ngAfterViewInit () {
|
||||
this.pluginService.initializeCustomModal(this.customModal)
|
||||
}
|
||||
|
||||
isUserLoggedIn () {
|
||||
return this.authService.isLoggedIn()
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-
|
|||
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({
|
||||
|
@ -47,6 +48,7 @@ export function metaFactory (serverService: ServerService): MetaLoader {
|
|||
SuggestionsComponent,
|
||||
SuggestionComponent,
|
||||
|
||||
CustomModalComponent,
|
||||
WelcomeModalComponent,
|
||||
InstanceConfigWarningModalComponent
|
||||
],
|
||||
|
|
|
@ -20,6 +20,7 @@ import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
|
|||
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
|
||||
|
@ -49,6 +50,8 @@ export class PluginService implements ClientHook {
|
|||
|
||||
translationsObservable: Observable<PluginTranslation>
|
||||
|
||||
customModal: CustomModalComponent
|
||||
|
||||
private plugins: ServerConfigPlugin[] = []
|
||||
private scopes: { [ scopeName: string ]: PluginInfo[] } = {}
|
||||
private loadedScripts: { [ script: string ]: boolean } = {}
|
||||
|
@ -81,6 +84,10 @@ export class PluginService implements ClientHook {
|
|||
})
|
||||
}
|
||||
|
||||
initializeCustomModal (customModal: CustomModalComponent) {
|
||||
this.customModal = customModal
|
||||
}
|
||||
|
||||
ensurePluginsAreBuilt () {
|
||||
return this.pluginsBuilt.asObservable()
|
||||
.pipe(first(), shareReplay())
|
||||
|
@ -279,6 +286,16 @@ export class PluginService implements ClientHook {
|
|||
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]))
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<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>
|
|
@ -0,0 +1,20 @@
|
|||
@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;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
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
|
||||
}
|
||||
}
|
|
@ -19,5 +19,13 @@ export type RegisterClientHelpers = {
|
|||
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>
|
||||
}
|
||||
|
|
|
@ -216,6 +216,24 @@ notifier.success('Success message content.')
|
|||
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):
|
||||
|
|
Loading…
Reference in New Issue