From 43d0ea7f4b88d52097172cc0c1831edd7e492503 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 28 Aug 2019 14:40:06 +0200 Subject: Add welcome modal --- client/src/app/app.component.html | 5 ++ client/src/app/app.component.ts | 45 ++++++++++++++- client/src/app/app.module.ts | 7 ++- .../instance-config-warning-modal.component.html | 15 +++++ .../instance-config-warning-modal.component.scss | 6 ++ .../instance-config-warning-modal.component.ts | 23 ++++++++ client/src/app/modal/welcome-modal.component.html | 66 ++++++++++++++++++++++ client/src/app/modal/welcome-modal.component.scss | 31 ++++++++++ client/src/app/modal/welcome-modal.component.ts | 40 +++++++++++++ client/src/app/shared/users/user.model.ts | 33 ++++++++--- 10 files changed, 259 insertions(+), 12 deletions(-) create mode 100644 client/src/app/modal/instance-config-warning-modal.component.html create mode 100644 client/src/app/modal/instance-config-warning-modal.component.scss create mode 100644 client/src/app/modal/instance-config-warning-modal.component.ts create mode 100644 client/src/app/modal/welcome-modal.component.html create mode 100644 client/src/app/modal/welcome-modal.component.scss create mode 100644 client/src/app/modal/welcome-modal.component.ts (limited to 'client/src') diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html index 07a576083..81b4351c5 100644 --- a/client/src/app/app.component.html +++ b/client/src/app/app.component.html @@ -54,3 +54,8 @@ + + + + + diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 64bfb9671..f68641047 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts @@ -1,10 +1,10 @@ -import { Component, OnInit } from '@angular/core' +import { Component, OnInit, ViewChild } 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 { is18nPath } from '../../../shared/models/i18n' import { ScreenService } from '@app/shared/misc/screen.service' -import { debounceTime, filter, map, pairwise, skip } from 'rxjs/operators' +import { debounceTime, filter, map, pairwise, skip, switchMap } from 'rxjs/operators' import { Hotkey, HotkeysService } from 'angular2-hotkeys' import { I18n } from '@ngx-translate/i18n-polyfill' import { fromEvent } from 'rxjs' @@ -13,6 +13,11 @@ import { PluginService } from '@app/core/plugins/plugin.service' import { HooksService } from '@app/core/plugins/hooks.service' 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 { UserRole } from '@shared/models' +import { User } from '@app/shared' +import { InstanceService } from '@app/shared/instance/instance.service' @Component({ selector: 'my-app', @@ -20,6 +25,9 @@ import { POP_STATE_MODAL_DISMISS } from '@app/shared/misc/constants' styleUrls: [ './app.component.scss' ] }) export class AppComponent implements OnInit { + @ViewChild('welcomeModal', { static: false }) welcomeModal: WelcomeModalComponent + @ViewChild('instanceConfigWarningModal', { static: false }) instanceConfigWarningModal: InstanceConfigWarningModalComponent + isMenuDisplayed = true isMenuChangedByUser = false @@ -32,6 +40,7 @@ export class AppComponent implements OnInit { private authService: AuthService, private serverService: ServerService, private pluginService: PluginService, + private instanceService: InstanceService, private domSanitizer: DomSanitizer, private redirectService: RedirectService, private screenService: ScreenService, @@ -96,6 +105,8 @@ export class AppComponent implements OnInit { .subscribe(() => this.onResize()) this.location.onPopState(() => this.modalService.dismissAll(POP_STATE_MODAL_DISMISS)) + + this.openModalsIfNeeded() } isUserLoggedIn () { @@ -220,32 +231,62 @@ export class AppComponent implements OnInit { this.hooks.runAction('action:application.init', 'common') } + private async openModalsIfNeeded () { + this.serverService.configLoaded + .pipe( + switchMap(() => this.authService.userInformationLoaded), + map(() => this.authService.getUser()), + filter(user => user.role === UserRole.ADMINISTRATOR) + ).subscribe(user => setTimeout(() => this.openAdminModals(user))) // setTimeout because of ngIf in template + } + + private async openAdminModals (user: User) { + if (user.noWelcomeModal !== true) return this.welcomeModal.show() + + const config = this.serverService.getConfig() + + if (user.noInstanceConfigWarningModal !== true && config.signup.allowed && config.instance.name.toLowerCase() === 'peertube') { + this.instanceService.getAbout() + .subscribe(about => { + if (!about.instance.terms) { + this.instanceConfigWarningModal.show() + } + }) + } + } + private initHotkeys () { this.hotkeysService.add([ new Hotkey(['/', 's'], (event: KeyboardEvent): boolean => { document.getElementById('search-video').focus() return false }, undefined, this.i18n('Focus the search bar')), + new Hotkey('b', (event: KeyboardEvent): boolean => { this.toggleMenu() return false }, undefined, this.i18n('Toggle the left menu')), + new Hotkey('g o', (event: KeyboardEvent): boolean => { this.router.navigate([ '/videos/overview' ]) return false }, undefined, this.i18n('Go to the discover videos page')), + new Hotkey('g t', (event: KeyboardEvent): boolean => { this.router.navigate([ '/videos/trending' ]) return false }, undefined, this.i18n('Go to the trending videos page')), + new Hotkey('g r', (event: KeyboardEvent): boolean => { this.router.navigate([ '/videos/recently-added' ]) return false }, undefined, this.i18n('Go to the recently added videos page')), + new Hotkey('g l', (event: KeyboardEvent): boolean => { this.router.navigate([ '/videos/local' ]) return false }, undefined, this.i18n('Go to the local videos page')), + new Hotkey('g u', (event: KeyboardEvent): boolean => { this.router.navigate([ '/videos/upload' ]) return false diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index 1e2936a37..a3ea33ca9 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts @@ -18,6 +18,8 @@ import { VideosModule } from './videos' import { buildFileLocale, getCompleteLocale, isDefaultLocale } from '../../../shared/models/i18n' import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils' import { SearchModule } from '@app/search' +import { WelcomeModalComponent } from '@app/modal/welcome-modal.component' +import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' export function metaFactory (serverService: ServerService): MetaLoader { return new MetaStaticLoader({ @@ -39,7 +41,10 @@ export function metaFactory (serverService: ServerService): MetaLoader { MenuComponent, LanguageChooserComponent, AvatarNotificationComponent, - HeaderComponent + HeaderComponent, + + WelcomeModalComponent, + InstanceConfigWarningModalComponent ], imports: [ BrowserModule, diff --git a/client/src/app/modal/instance-config-warning-modal.component.html b/client/src/app/modal/instance-config-warning-modal.component.html new file mode 100644 index 000000000..595afb103 --- /dev/null +++ b/client/src/app/modal/instance-config-warning-modal.component.html @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/client/src/app/modal/instance-config-warning-modal.component.scss b/client/src/app/modal/instance-config-warning-modal.component.scss new file mode 100644 index 000000000..51834c649 --- /dev/null +++ b/client/src/app/modal/instance-config-warning-modal.component.scss @@ -0,0 +1,6 @@ +@import '_mixins'; +@import '_variables'; + +.action-button-cancel { + margin-right: 0 !important; +} diff --git a/client/src/app/modal/instance-config-warning-modal.component.ts b/client/src/app/modal/instance-config-warning-modal.component.ts new file mode 100644 index 000000000..5cc9207cd --- /dev/null +++ b/client/src/app/modal/instance-config-warning-modal.component.ts @@ -0,0 +1,23 @@ +import { Component, ElementRef, ViewChild } from '@angular/core' +import { Notifier } from '@app/core' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { NgbModal } from '@ng-bootstrap/ng-bootstrap' + +@Component({ + selector: 'my-instance-config-warning-modal', + templateUrl: './instance-config-warning-modal.component.html', + styleUrls: [ './instance-config-warning-modal.component.scss' ] +}) +export class InstanceConfigWarningModalComponent { + @ViewChild('modal', { static: true }) modal: ElementRef + + constructor ( + private modalService: NgbModal, + private notifier: Notifier, + private i18n: I18n + ) { } + + show () { + this.modalService.open(this.modal) + } +} diff --git a/client/src/app/modal/welcome-modal.component.html b/client/src/app/modal/welcome-modal.component.html new file mode 100644 index 000000000..c83b53c2c --- /dev/null +++ b/client/src/app/modal/welcome-modal.component.html @@ -0,0 +1,66 @@ + + + + + + + + diff --git a/client/src/app/modal/welcome-modal.component.scss b/client/src/app/modal/welcome-modal.component.scss new file mode 100644 index 000000000..ab57bb993 --- /dev/null +++ b/client/src/app/modal/welcome-modal.component.scss @@ -0,0 +1,31 @@ +@import '_mixins'; +@import '_variables'; + +.modal-body { + font-size: 15px; +} + +.action-button-cancel { + margin-right: 0 !important; +} + +.subtitle { + font-weight: $font-semibold; + margin-bottom: 10px; + font-size: 16px; +} + +.block-configuration, +.block-instance { + margin-top: 30px; +} + +li { + margin-bottom: 10px; +} + +.configure-instance { + text-align: center; + font-weight: 600; + font-size: 18px; +} diff --git a/client/src/app/modal/welcome-modal.component.ts b/client/src/app/modal/welcome-modal.component.ts new file mode 100644 index 000000000..bff2968d4 --- /dev/null +++ b/client/src/app/modal/welcome-modal.component.ts @@ -0,0 +1,40 @@ +import { Component, ElementRef, ViewChild } from '@angular/core' +import { Notifier } from '@app/core' +import { NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { UserService } from '@app/shared' + +@Component({ + selector: 'my-welcome-modal', + templateUrl: './welcome-modal.component.html', + styleUrls: [ './welcome-modal.component.scss' ] +}) +export class WelcomeModalComponent { + @ViewChild('modal', { static: true }) modal: ElementRef + + constructor ( + private userService: UserService, + private modalService: NgbModal, + private notifier: Notifier + ) { } + + show () { + const ref = this.modalService.open(this.modal,{ + backdrop: 'static', + keyboard: false, + size: 'lg' + }) + + ref.result.finally(() => this.doNotOpenAgain()) + } + + private doNotOpenAgain () { + this.userService.updateMyProfile({ noWelcomeModal: true }) + .subscribe( + () => console.log('We will not open the welcome modal again.'), + + err => this.notifier.error(err.message) + ) + + return true + } +} diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts index 53809f82c..656b73dd2 100644 --- a/client/src/app/shared/users/user.model.ts +++ b/client/src/app/shared/users/user.model.ts @@ -9,31 +9,38 @@ export class User implements UserServerModel { username: string email: string pendingEmail: string | null + emailVerified: boolean nsfwPolicy: NSFWPolicyType - role: UserRole - roleLabel: string + adminFlags?: UserAdminFlag - webTorrentEnabled: boolean autoPlayVideo: boolean + webTorrentEnabled: boolean videosHistoryEnabled: boolean videoLanguages: string[] + role: UserRole + roleLabel: string + videoQuota: number videoQuotaDaily: number - account: Account - videoChannels: VideoChannel[] - createdAt: Date + videoQuotaUsed?: number + videoQuotaUsedDaily?: number theme: string - adminFlags?: UserAdminFlag + account: Account + notificationSettings?: UserNotificationSetting + videoChannels?: VideoChannel[] blocked: boolean blockedReason?: string - notificationSettings?: UserNotificationSetting + noInstanceConfigWarningModal: boolean + noWelcomeModal: boolean + + createdAt: Date constructor (hash: Partial) { this.id = hash.id @@ -43,13 +50,16 @@ export class User implements UserServerModel { this.role = hash.role this.videoChannels = hash.videoChannels + this.videoQuota = hash.videoQuota this.videoQuotaDaily = hash.videoQuotaDaily + this.videoQuotaUsed = hash.videoQuotaUsed + this.videoQuotaUsedDaily = hash.videoQuotaUsedDaily + this.nsfwPolicy = hash.nsfwPolicy this.webTorrentEnabled = hash.webTorrentEnabled this.videosHistoryEnabled = hash.videosHistoryEnabled this.autoPlayVideo = hash.autoPlayVideo - this.createdAt = hash.createdAt this.theme = hash.theme @@ -58,8 +68,13 @@ export class User implements UserServerModel { this.blocked = hash.blocked this.blockedReason = hash.blockedReason + this.noInstanceConfigWarningModal = hash.noInstanceConfigWarningModal + this.noWelcomeModal = hash.noWelcomeModal + this.notificationSettings = hash.notificationSettings + this.createdAt = hash.createdAt + if (hash.account !== undefined) { this.account = new Account(hash.account) } -- cgit v1.2.3