Inform user to fill account profile and channels (#4352)
* Add account-setup modal when login * Add channels-setup alert into my-channels, my-playlists and upload page Co-authored-by: Ms Kimsible <kimsible@users.noreply.github.com>
This commit is contained in:
parent
8729a87024
commit
7dca45f99d
|
@ -526,7 +526,7 @@
|
|||
# Icons
|
||||
|
||||
* [Feather Icons](https://feathericons.com) (MIT)
|
||||
* `playlist add`, `history`, `subscriptions`, `miscellaneous-services.svg` by Material UI (Apache 2.0)
|
||||
* `playlist add`, `history`, `subscriptions`, `miscellaneous-services.svg`, `tip` by Material UI (Apache 2.0)
|
||||
* `support` by Chocobozzz (CC-BY)
|
||||
* `language` by Aaron Jin (CC-BY)
|
||||
* `video-language` by Rigel Kent (CC-BY)
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
<span class="badge badge-secondary">{{ totalItems }}</span>
|
||||
</h1>
|
||||
|
||||
<my-channels-setup-message [hideLink]="true"></my-channels-setup-message>
|
||||
|
||||
<div class="video-channels-header d-flex justify-content-between">
|
||||
<my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
<ng-container i18n>My playlists</ng-container> <span class="badge badge-secondary">{{ pagination.totalItems }}</span>
|
||||
</h1>
|
||||
|
||||
<my-channels-setup-message></my-channels-setup-message>
|
||||
|
||||
<div class="video-playlists-header d-flex justify-content-between">
|
||||
<my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
<ng-container *ngIf="secondStepType === 'upload'" i18n>Upload {{ videoName }}</ng-container>
|
||||
</div>
|
||||
|
||||
<my-channels-setup-message></my-channels-setup-message>
|
||||
|
||||
<div ngbNav #nav="ngbNav" class="nav-tabs video-add-nav" [activeId]="activeNav" (activeIdChange)="onNavChange($event)" [ngClass]="{ 'hide-nav': !!secondStepType }">
|
||||
<ng-container ngbNavItem="upload">
|
||||
<a ngbNavLink>
|
||||
|
|
|
@ -60,9 +60,10 @@
|
|||
</ng-template>
|
||||
</p-toast>
|
||||
|
||||
<ng-template [ngIf]="isUserLoggedIn()">
|
||||
<ng-container *ngIf="isUserLoggedIn()">
|
||||
<my-account-setup-modal #accountSetupModal></my-account-setup-modal>
|
||||
<my-welcome-modal #welcomeModal></my-welcome-modal>
|
||||
<my-instance-config-warning-modal #instanceConfigWarningModal></my-instance-config-warning-modal>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
<my-custom-modal #customModal></my-custom-modal>
|
||||
|
|
|
@ -20,6 +20,7 @@ import { PluginService } from '@app/core/plugins/plugin.service'
|
|||
import { CustomModalComponent } from '@app/modal/custom-modal.component'
|
||||
import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component'
|
||||
import { WelcomeModalComponent } from '@app/modal/welcome-modal.component'
|
||||
import { AccountSetupModalComponent } from '@app/modal/account-setup-modal.component'
|
||||
import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
|
||||
|
@ -37,6 +38,7 @@ import { InstanceService } from './shared/shared-instance'
|
|||
export class AppComponent implements OnInit, AfterViewInit {
|
||||
private static BROADCAST_MESSAGE_KEY = 'app-broadcast-message-dismissed'
|
||||
|
||||
@ViewChild('accountSetupModal') accountSetupModal: AccountSetupModalComponent
|
||||
@ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent
|
||||
@ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent
|
||||
@ViewChild('customModal') customModal: CustomModalComponent
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CustomModalComponent } from './modal/custom-modal.component'
|
|||
import { InstanceConfigWarningModalComponent } from './modal/instance-config-warning-modal.component'
|
||||
import { QuickSettingsModalComponent } from './modal/quick-settings-modal.component'
|
||||
import { WelcomeModalComponent } from './modal/welcome-modal.component'
|
||||
import { AccountSetupModalComponent } from './modal/account-setup-modal.component'
|
||||
import { SharedActorImageModule } from './shared/shared-actor-image/shared-actor-image.module'
|
||||
import { SharedFormModule } from './shared/shared-forms'
|
||||
import { SharedGlobalIconModule } from './shared/shared-icons'
|
||||
|
@ -53,6 +54,7 @@ export function loadConfigFactory (server: ServerService, pluginService: PluginS
|
|||
SuggestionComponent,
|
||||
HighlightPipe,
|
||||
|
||||
AccountSetupModalComponent,
|
||||
CustomModalComponent,
|
||||
WelcomeModalComponent,
|
||||
InstanceConfigWarningModalComponent,
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<ng-template #modal let-hide="close">
|
||||
<div class="modal-header">
|
||||
<h4 i18n class="modal-title">Welcome to {{ instanceName }}, dear user!</h4>
|
||||
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<img class="mascot" src="/client/assets/images/mascot/happy.svg" alt="mascot">
|
||||
|
||||
<div i18n class="subtitle">It's time to set up your account profile!</div>
|
||||
|
||||
<p i18n>Help moderators and other users to know <strong>who you are</strong> by:</p>
|
||||
|
||||
<ul>
|
||||
<li *ngIf="!hasAccountAvatar" i18n>Uploading an <strong>avatar</strong></li>
|
||||
<li *ngIf="!hasAccountDescription" i18n>Writing a <strong>description</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer inputs">
|
||||
<input
|
||||
type="button" role="button" i18n-value value="Remind me later" class="peertube-button grey-button"
|
||||
(click)="hide()" (key.enter)="hide()"
|
||||
>
|
||||
|
||||
<a i18n (click)="hide()" (key.enter)="hide()"
|
||||
class="peertube-button-link orange-button" routerLink="/my-account"
|
||||
rel="noopener noreferrer" ngbAutofocus>
|
||||
Set up
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</ng-template>
|
|
@ -0,0 +1,31 @@
|
|||
@use '_mixins' as *;
|
||||
@use '_variables' as *;
|
||||
|
||||
.modal-body {
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mascot-fw {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
.mascot {
|
||||
@include margin-right(2rem);
|
||||
|
||||
display: block;
|
||||
min-width: 170px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-weight: $font-semibold;
|
||||
margin-bottom: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 10px;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
|
||||
import { AuthService, ServerService, User } from '@app/core'
|
||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { HTMLServerConfig } from '@shared/models'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account-setup-modal',
|
||||
templateUrl: './account-setup-modal.component.html',
|
||||
styleUrls: [ './account-setup-modal.component.scss' ]
|
||||
})
|
||||
export class AccountSetupModalComponent implements OnInit {
|
||||
@ViewChild('modal', { static: true }) modal: ElementRef
|
||||
|
||||
user: User = null
|
||||
ref: NgbModalRef = null
|
||||
|
||||
private serverConfig: HTMLServerConfig
|
||||
|
||||
constructor (
|
||||
private authService: AuthService,
|
||||
private modalService: NgbModal,
|
||||
private serverService: ServerService
|
||||
) { }
|
||||
|
||||
get userInformationLoaded () {
|
||||
return this.authService.userInformationLoaded
|
||||
}
|
||||
|
||||
get instanceName () {
|
||||
return this.serverConfig.instance.name
|
||||
}
|
||||
|
||||
get isUserRoot () {
|
||||
return this.user.username === 'root'
|
||||
}
|
||||
|
||||
get hasAccountAvatar () {
|
||||
return !!this.user.account.avatar
|
||||
}
|
||||
|
||||
get hasAccountDescription () {
|
||||
return !!this.user.account.description
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
this.serverConfig = this.serverService.getHTMLConfig()
|
||||
this.user = this.authService.getUser()
|
||||
|
||||
this.authService.userInformationLoaded
|
||||
.subscribe(
|
||||
() => {
|
||||
if (this.isUserRoot) return false
|
||||
if (this.hasAccountAvatar && this.hasAccountDescription) return false
|
||||
|
||||
this.show()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
show () {
|
||||
if (this.ref) return false
|
||||
|
||||
this.ref = this.modalService.open(this.modal, {
|
||||
centered: true,
|
||||
backdrop: 'static',
|
||||
keyboard: false,
|
||||
size: 'md'
|
||||
})
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ const icons = {
|
|||
'playlist-add': require('!!raw-loader?!../../../assets/images/misc/playlist-add.svg').default, // material ui
|
||||
follower: require('!!raw-loader?!../../../assets/images/misc/account-arrow-left.svg').default, // material ui
|
||||
following: require('!!raw-loader?!../../../assets/images/misc/account-arrow-right.svg').default, // material ui
|
||||
tip: require('!!raw-loader?!../../../assets/images/misc/tip.svg').default, // material ui
|
||||
flame: require('!!raw-loader?!../../../assets/images/misc/flame.svg').default,
|
||||
local: require('!!raw-loader?!../../../assets/images/misc/local.svg').default,
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<div *ngIf="hasChannelNotConfigured" class="channels-setup-message alert alert-info">
|
||||
<my-global-icon iconName="tip"></my-global-icon>
|
||||
|
||||
<div>
|
||||
<div i18n>Some of your channels are not fully set up. Make them welcoming and explicit about what you publish by adding a <strong>banner</strong>, an <strong>avatar</strong> and a <strong>description</strong>.</div>
|
||||
<a *ngIf="!hideLink" class="channels-settings-link" routerLink="/my-library/video-channels" i18n>Set up my channels</a>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,32 @@
|
|||
@use '_variables' as *;
|
||||
@use '_mixins' as *;
|
||||
|
||||
.channels-setup-message {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
my-global-icon {
|
||||
width: 32px;
|
||||
align-self: flex-start;
|
||||
|
||||
::ng-deep {
|
||||
svg {
|
||||
fill: #0c5460;
|
||||
}
|
||||
}
|
||||
|
||||
+ div {
|
||||
margin-left: 10px;
|
||||
text-align: center;
|
||||
|
||||
a.channels-settings-link {
|
||||
@include peertube-button-link;
|
||||
@include grey-button;
|
||||
|
||||
height: fit-content;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { Component, Input, OnInit } from '@angular/core'
|
||||
import { AuthService, User } from '@app/core'
|
||||
import { VideoChannel } from '@app/shared/shared-main'
|
||||
|
||||
@Component({
|
||||
selector: 'my-channels-setup-message',
|
||||
templateUrl: './channels-setup-message.component.html',
|
||||
styleUrls: [ './channels-setup-message.component.scss' ]
|
||||
})
|
||||
export class ChannelsSetupMessageComponent implements OnInit {
|
||||
@Input() hideLink = false
|
||||
|
||||
user: User = null
|
||||
|
||||
constructor (
|
||||
private authService: AuthService
|
||||
) {}
|
||||
|
||||
get userInformationLoaded () {
|
||||
return this.authService.userInformationLoaded
|
||||
}
|
||||
|
||||
get hasChannelNotConfigured () {
|
||||
return this.user.videoChannels
|
||||
.filter((channel: VideoChannel) => (!channel.avatar || !channel.description))
|
||||
.length > 0
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
this.user = this.authService.getUser()
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
export * from './channels-setup-message.component'
|
||||
export * from './help.component'
|
||||
export * from './list-overflow.component'
|
||||
export * from './top-menu-dropdown.component'
|
||||
|
|
|
@ -34,7 +34,13 @@ import { CustomPageService } from './custom-page'
|
|||
import { DateToggleComponent } from './date'
|
||||
import { FeedComponent } from './feeds'
|
||||
import { LoaderComponent, SmallLoaderComponent } from './loaders'
|
||||
import { HelpComponent, ListOverflowComponent, SimpleSearchInputComponent, TopMenuDropdownComponent } from './misc'
|
||||
import {
|
||||
ChannelsSetupMessageComponent,
|
||||
HelpComponent,
|
||||
ListOverflowComponent,
|
||||
SimpleSearchInputComponent,
|
||||
TopMenuDropdownComponent
|
||||
} from './misc'
|
||||
import { PluginPlaceholderComponent } from './plugins'
|
||||
import { ActorRedirectGuard } from './router'
|
||||
import { UserHistoryService, UserNotificationsComponent, UserNotificationService, UserQuotaComponent } from './users'
|
||||
|
@ -91,6 +97,7 @@ import { VideoChannelService } from './video-channel'
|
|||
LoaderComponent,
|
||||
SmallLoaderComponent,
|
||||
|
||||
ChannelsSetupMessageComponent,
|
||||
HelpComponent,
|
||||
ListOverflowComponent,
|
||||
TopMenuDropdownComponent,
|
||||
|
@ -146,6 +153,7 @@ import { VideoChannelService } from './video-channel'
|
|||
LoaderComponent,
|
||||
SmallLoaderComponent,
|
||||
|
||||
ChannelsSetupMessageComponent,
|
||||
HelpComponent,
|
||||
ListOverflowComponent,
|
||||
TopMenuDropdownComponent,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><g><rect height="3" width="2" x="11" y="19"/><rect height="2" width="3" x="2" y="11"/><rect height="2" width="3" x="19" y="11"/><rect height="3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -7.6665 17.8014)" width="1.99" x="16.66" y="16.66"/><rect height="1.99" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -10.9791 9.8041)" width="3" x="4.85" y="17.16"/><path d="M15,8.02V3H9v5.02C7.79,8.94,7,10.37,7,12c0,2.76,2.24,5,5,5s5-2.24,5-5C17,10.37,16.21,8.94,15,8.02z M11,5h2v2.1 C12.68,7.04,12.34,7,12,7s-0.68,0.04-1,0.1V5z"/></g></g></svg>
|
After Width: | Height: | Size: 726 B |
Loading…
Reference in New Issue