Merge pull request #5283 from tsiegleauq/user-active-toggle
Add set present toggle in user menu
This commit is contained in:
commit
8119507b8a
@ -416,6 +416,13 @@ export class OperatorService implements OnAfterAppsLoaded {
|
|||||||
this.operatorSubject.next(this.user);
|
this.operatorSubject.next(this.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the operators presence to isPresent
|
||||||
|
*/
|
||||||
|
public async setPresence(isPresent: boolean): Promise<void> {
|
||||||
|
await this.http.post(environment.urlPrefix + '/users/setpresence/', isPresent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a default WhoAmI response
|
* Returns a default WhoAmI response
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
<mat-expansion-panel class="user-menu mat-elevation-z0">
|
||||||
|
<mat-expansion-panel-header class="username">
|
||||||
|
<!-- Get the username from operator -->
|
||||||
|
{{ username }}
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<mat-nav-list>
|
||||||
|
<!-- select languate -->
|
||||||
|
<a mat-list-item [matMenuTriggerFor]="languageMenu">
|
||||||
|
<mat-icon class="menu-icon">language</mat-icon>
|
||||||
|
<span class="menu-text">{{ getLangName() }}</span>
|
||||||
|
</a>
|
||||||
|
<div *ngIf="user && isLoggedIn">
|
||||||
|
<!-- present toggle -->
|
||||||
|
<button
|
||||||
|
[ngClass]="{ active: user.is_present }"
|
||||||
|
mat-menu-item
|
||||||
|
(click)="toggleUserIsPresent()"
|
||||||
|
*ngIf="allowSelfSetPresent"
|
||||||
|
>
|
||||||
|
<mat-icon [color]="user.is_present ? 'primary' : ''" class="menu-icon">
|
||||||
|
{{ user.is_present ? 'check_box' : 'check_box_outline_blank' }}
|
||||||
|
</mat-icon>
|
||||||
|
<span class="menu-text" translate>Present</span>
|
||||||
|
</button>
|
||||||
|
<!-- Show profile -->
|
||||||
|
<a
|
||||||
|
[ngClass]="{ active: isOnProfilePage() }"
|
||||||
|
[routerLink]="user ? ['/users/', user.id] : []"
|
||||||
|
(click)="onClickNavEntry()"
|
||||||
|
mat-list-item
|
||||||
|
>
|
||||||
|
<mat-icon class="menu-icon">person</mat-icon>
|
||||||
|
<span class="menu-text" translate>Show profile</span>
|
||||||
|
</a>
|
||||||
|
<!-- Change password -->
|
||||||
|
<ng-container *ngIf="authType === 'default'">
|
||||||
|
<a
|
||||||
|
[ngClass]="{ active: isOnChangePasswordPage() }"
|
||||||
|
*osPerms="'users.can_change_password'"
|
||||||
|
routerLink="/users/password"
|
||||||
|
(click)="onClickNavEntry()"
|
||||||
|
mat-list-item
|
||||||
|
>
|
||||||
|
<mat-icon class="menu-icon">vpn_key</mat-icon>
|
||||||
|
<span class="menu-text" translate>Change password</span>
|
||||||
|
</a>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngIf="authType === 'saml'">
|
||||||
|
<a *osPerms="'users.can_change_password'" [href]="samlChangePasswordUrl" mat-list-item>
|
||||||
|
<mat-icon class="menu-icon">vpn_key</mat-icon>
|
||||||
|
<span class="menu-text" translate>Change password</span>
|
||||||
|
</a>
|
||||||
|
</ng-container>
|
||||||
|
<!-- logout -->
|
||||||
|
<a (click)="logout()" mat-list-item>
|
||||||
|
<mat-icon class="menu-icon">exit_to_app</mat-icon>
|
||||||
|
<span class="menu-text" translate>Logout</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</mat-nav-list>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
<mat-nav-list *ngIf="!isLoggedIn">
|
||||||
|
<a routerLink="/login" mat-list-item>
|
||||||
|
<mat-icon class="menu-icon">exit_to_app</mat-icon>
|
||||||
|
<span class="menu-text" translate>Login</span>
|
||||||
|
</a>
|
||||||
|
</mat-nav-list>
|
||||||
|
|
||||||
|
<mat-menu #languageMenu="matMenu">
|
||||||
|
<button mat-menu-item (click)="selectLang('en')">{{ getLangName('en') }}</button>
|
||||||
|
<button mat-menu-item (click)="selectLang('de')">{{ getLangName('de') }}</button>
|
||||||
|
<button mat-menu-item (click)="selectLang('ru')">{{ getLangName('ru') }}</button>
|
||||||
|
<button mat-menu-item (click)="selectLang('cs')">{{ getLangName('cs') }}</button>
|
||||||
|
</mat-menu>
|
@ -0,0 +1,16 @@
|
|||||||
|
.username {
|
||||||
|
span {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
min-width: 20px !important; //puts the text to the right on the same level
|
||||||
|
margin-right: 25px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-text {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { E2EImportsModule } from 'e2e-imports.module';
|
||||||
|
|
||||||
|
import { UserMenuComponent } from './user-menu.component';
|
||||||
|
|
||||||
|
describe('UserMenuComponent', () => {
|
||||||
|
let component: UserMenuComponent;
|
||||||
|
let fixture: ComponentFixture<UserMenuComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(UserMenuComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,137 @@
|
|||||||
|
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||||
|
import { MatSnackBar } from '@angular/material';
|
||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { AuthService } from 'app/core/core-services/auth.service';
|
||||||
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
|
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
||||||
|
import { OverlayService } from 'app/core/ui-services/overlay.service';
|
||||||
|
import { DEFAULT_AUTH_TYPE } from 'app/shared/models/users/user';
|
||||||
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
|
import { ViewUser } from 'app/site/users/models/view-user';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'os-user-menu',
|
||||||
|
templateUrl: './user-menu.component.html',
|
||||||
|
styleUrls: ['./user-menu.component.scss']
|
||||||
|
})
|
||||||
|
export class UserMenuComponent extends BaseViewComponent implements OnInit {
|
||||||
|
public isLoggedIn: boolean;
|
||||||
|
|
||||||
|
public user: ViewUser;
|
||||||
|
|
||||||
|
public username = '';
|
||||||
|
|
||||||
|
public authType = DEFAULT_AUTH_TYPE;
|
||||||
|
|
||||||
|
public samlChangePasswordUrl: string | null = null;
|
||||||
|
|
||||||
|
public allowSelfSetPresent: boolean;
|
||||||
|
|
||||||
|
private selfPresentConfStr = 'users_allow_self_set_present';
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
private navEvent: EventEmitter<void> = new EventEmitter();
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
titleService: Title,
|
||||||
|
protected translate: TranslateService,
|
||||||
|
protected matSnackBar: MatSnackBar,
|
||||||
|
private operator: OperatorService,
|
||||||
|
private authService: AuthService,
|
||||||
|
private overlayService: OverlayService, // private vp: ViewportService,
|
||||||
|
private loginDataService: LoginDataService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
super(titleService, translate, matSnackBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.operator.getViewUserObservable().subscribe(user => {
|
||||||
|
if (user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
if (!this.operator.isAnonymous) {
|
||||||
|
this.username = user ? user.short_name : '';
|
||||||
|
this.isLoggedIn = true;
|
||||||
|
} else {
|
||||||
|
this.username = this.translate.instant('Guest');
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.operator.authType.subscribe(authType => (this.authType = authType));
|
||||||
|
|
||||||
|
this.loginDataService.samlSettings.subscribe(
|
||||||
|
samlSettings => (this.samlChangePasswordUrl = samlSettings ? samlSettings.changePasswordUrl : null)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.configService
|
||||||
|
.get<boolean>(this.selfPresentConfStr)
|
||||||
|
.subscribe(allowed => (this.allowSelfSetPresent = allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOnProfilePage(): boolean {
|
||||||
|
const ownProfilePageUrl = `/users/${this.user.id}`;
|
||||||
|
return ownProfilePageUrl === this.router.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOnChangePasswordPage(): boolean {
|
||||||
|
const changePasswordPageUrl = '/users/password';
|
||||||
|
return changePasswordPageUrl === this.router.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Let the user change the language
|
||||||
|
* @param lang the desired language (en, de, cs, ...)
|
||||||
|
*/
|
||||||
|
public selectLang(selection: string): void {
|
||||||
|
this.translate.use(selection).subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of a Language by abbreviation.
|
||||||
|
*
|
||||||
|
* @param abbreviation The abbreviation of the languate or null, if the current
|
||||||
|
* language should be used.
|
||||||
|
*/
|
||||||
|
public getLangName(abbreviation?: string): string {
|
||||||
|
if (!abbreviation) {
|
||||||
|
abbreviation = this.translate.currentLang;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abbreviation === 'en') {
|
||||||
|
return 'English';
|
||||||
|
} else if (abbreviation === 'de') {
|
||||||
|
return 'Deutsch';
|
||||||
|
} else if (abbreviation === 'cs') {
|
||||||
|
return 'Čeština';
|
||||||
|
} else if (abbreviation === 'ru') {
|
||||||
|
return 'русский';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleUserIsPresent(): void {
|
||||||
|
this.operator.setPresence(!this.user.is_present).catch(this.raiseError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onClickNavEntry(): void {
|
||||||
|
this.navEvent.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to log out the current user
|
||||||
|
*/
|
||||||
|
public logout(): void {
|
||||||
|
if (this.operator.guestsEnabled) {
|
||||||
|
this.overlayService.showSpinner(null, true);
|
||||||
|
}
|
||||||
|
this.authService.logout();
|
||||||
|
this.overlayService.logout();
|
||||||
|
}
|
||||||
|
}
|
@ -107,7 +107,7 @@ import { SuperSearchComponent } from 'app/site/common/components/super-search/su
|
|||||||
import { OverlayComponent } from 'app/site/common/components/overlay/overlay.component';
|
import { OverlayComponent } from 'app/site/common/components/overlay/overlay.component';
|
||||||
import { PreviewComponent } from './components/preview/preview.component';
|
import { PreviewComponent } from './components/preview/preview.component';
|
||||||
import { PdfViewerModule } from 'ng2-pdf-viewer';
|
import { PdfViewerModule } from 'ng2-pdf-viewer';
|
||||||
import { GlobalSpinnerComponent } from 'app/site/common/components/global-spinner/global-spinner.component';
|
|
||||||
import { HeightResizingDirective } from './directives/height-resizing.directive';
|
import { HeightResizingDirective } from './directives/height-resizing.directive';
|
||||||
import { TrustPipe } from './pipes/trust.pipe';
|
import { TrustPipe } from './pipes/trust.pipe';
|
||||||
import { LocalizedDatePipe } from './pipes/localized-date.pipe';
|
import { LocalizedDatePipe } from './pipes/localized-date.pipe';
|
||||||
@ -125,6 +125,9 @@ import { VotingPrivacyWarningComponent } from './components/voting-privacy-warni
|
|||||||
import { MotionPollDetailContentComponent } from './components/motion-poll-detail-content/motion-poll-detail-content.component';
|
import { MotionPollDetailContentComponent } from './components/motion-poll-detail-content/motion-poll-detail-content.component';
|
||||||
import { AssignmentPollDetailContentComponent } from './components/assignment-poll-detail-content/assignment-poll-detail-content.component';
|
import { AssignmentPollDetailContentComponent } from './components/assignment-poll-detail-content/assignment-poll-detail-content.component';
|
||||||
|
|
||||||
|
import { GlobalSpinnerComponent } from './components/global-spinner/global-spinner.component';
|
||||||
|
import { UserMenuComponent } from './components/user-menu/user-menu.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Share Module for all "dumb" components and pipes.
|
* Share Module for all "dumb" components and pipes.
|
||||||
*
|
*
|
||||||
@ -272,6 +275,7 @@ import { AssignmentPollDetailContentComponent } from './components/assignment-po
|
|||||||
ExtensionFieldComponent,
|
ExtensionFieldComponent,
|
||||||
RoundedInputComponent,
|
RoundedInputComponent,
|
||||||
GlobalSpinnerComponent,
|
GlobalSpinnerComponent,
|
||||||
|
UserMenuComponent,
|
||||||
OverlayComponent,
|
OverlayComponent,
|
||||||
PreviewComponent,
|
PreviewComponent,
|
||||||
NgxMaterialTimepickerModule,
|
NgxMaterialTimepickerModule,
|
||||||
@ -332,6 +336,7 @@ import { AssignmentPollDetailContentComponent } from './components/assignment-po
|
|||||||
RoundedInputComponent,
|
RoundedInputComponent,
|
||||||
ProgressSnackBarComponent,
|
ProgressSnackBarComponent,
|
||||||
GlobalSpinnerComponent,
|
GlobalSpinnerComponent,
|
||||||
|
UserMenuComponent,
|
||||||
SuperSearchComponent,
|
SuperSearchComponent,
|
||||||
OverlayComponent,
|
OverlayComponent,
|
||||||
PreviewComponent,
|
PreviewComponent,
|
||||||
|
@ -15,83 +15,16 @@
|
|||||||
>
|
>
|
||||||
<div class="nav-toolbar">
|
<div class="nav-toolbar">
|
||||||
<!-- logo -->
|
<!-- logo -->
|
||||||
<a routerLink="/" (click)="toggleSideNav()">
|
<a routerLink="/" (click)="mobileAutoCloseNav()">
|
||||||
<os-logo class="os-logo-container" [footer]="false"></os-logo>
|
<os-logo class="os-logo-container" [footer]="false"></os-logo>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- User Menu -->
|
<!-- User Menu -->
|
||||||
<mat-expansion-panel class="user-menu mat-elevation-z0">
|
<os-user-menu (navEvent)="mobileAutoCloseNav()"></os-user-menu>
|
||||||
<mat-expansion-panel-header class="username">
|
|
||||||
<!-- Get the username from operator -->
|
|
||||||
{{ username }}
|
|
||||||
</mat-expansion-panel-header>
|
|
||||||
<mat-nav-list>
|
|
||||||
<a mat-list-item [matMenuTriggerFor]="languageMenu">
|
|
||||||
<mat-icon>language</mat-icon>
|
|
||||||
<span>{{ getLangName() }}</span>
|
|
||||||
</a>
|
|
||||||
<div *ngIf="isLoggedIn">
|
|
||||||
<a
|
|
||||||
[routerLink]="operator.user ? ['/users/', operator.user.id] : []"
|
|
||||||
(click)="mobileAutoCloseNav()"
|
|
||||||
mat-list-item
|
|
||||||
>
|
|
||||||
<mat-icon>person</mat-icon>
|
|
||||||
<span translate>Show profile</span>
|
|
||||||
</a>
|
|
||||||
<ng-container *ngIf="authType === 'default'">
|
|
||||||
<a
|
|
||||||
*osPerms="'users.can_change_password'"
|
|
||||||
routerLink="/users/password"
|
|
||||||
(click)="mobileAutoCloseNav()"
|
|
||||||
mat-list-item
|
|
||||||
>
|
|
||||||
<mat-icon>vpn_key</mat-icon>
|
|
||||||
<span translate>Change password</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="authType === 'saml'">
|
|
||||||
<a
|
|
||||||
*osPerms="'users.can_change_password'"
|
|
||||||
[href]="samlChangePasswordUrl"
|
|
||||||
mat-list-item
|
|
||||||
>
|
|
||||||
<mat-icon>vpn_key</mat-icon>
|
|
||||||
<span translate>Change password</span>
|
|
||||||
</a>
|
|
||||||
</ng-container>
|
|
||||||
<a (click)="logout()" mat-list-item>
|
|
||||||
<mat-icon>exit_to_app</mat-icon>
|
|
||||||
<span translate>Logout</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="!isLoggedIn">
|
|
||||||
<a routerLink="/login" mat-list-item>
|
|
||||||
<mat-icon>exit_to_app</mat-icon>
|
|
||||||
<span translate>Login</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</mat-nav-list>
|
|
||||||
</mat-expansion-panel>
|
|
||||||
<mat-menu #languageMenu="matMenu">
|
|
||||||
<button mat-menu-item (click)="selectLang('en')">{{ getLangName('en') }}</button>
|
|
||||||
<button mat-menu-item (click)="selectLang('de')">{{ getLangName('de') }}</button>
|
|
||||||
<button mat-menu-item (click)="selectLang('ru')">{{ getLangName('ru') }}</button>
|
|
||||||
<button mat-menu-item (click)="selectLang('cs')">{{ getLangName('cs') }}</button>
|
|
||||||
</mat-menu>
|
|
||||||
|
|
||||||
<!-- navigation -->
|
<!-- navigation -->
|
||||||
<mat-nav-list class="main-nav">
|
<mat-nav-list class="main-nav">
|
||||||
<ng-container *ngIf="!isLoggedIn">
|
|
||||||
<a routerLink="/login" mat-list-item>
|
|
||||||
<mat-icon>exit_to_app</mat-icon>
|
|
||||||
<span translate>Login</span>
|
|
||||||
</a>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<span *ngFor="let entry of mainMenuService.entries">
|
<span *ngFor="let entry of mainMenuService.entries">
|
||||||
<a
|
<a
|
||||||
[@navItemAnim]
|
[@navItemAnim]
|
||||||
|
@ -39,14 +39,6 @@ mat-sidenav-container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
|
||||||
span {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-toolbar {
|
.nav-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
@ -29,8 +29,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** style and align the nav icons the icons*/
|
/** style and align the nav icons the icons*/
|
||||||
.main-nav,
|
.main-nav {
|
||||||
.user-menu {
|
|
||||||
mat-icon {
|
mat-icon {
|
||||||
color: mat-color($foreground, icon);
|
color: mat-color($foreground, icon);
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,8 @@ import { filter } from 'rxjs/operators';
|
|||||||
|
|
||||||
import { navItemAnim } from '../shared/animations';
|
import { navItemAnim } from '../shared/animations';
|
||||||
import { OfflineService } from 'app/core/core-services/offline.service';
|
import { OfflineService } from 'app/core/core-services/offline.service';
|
||||||
import { LoginDataService } from 'app/core/ui-services/login-data.service';
|
|
||||||
import { OverlayService } from 'app/core/ui-services/overlay.service';
|
import { OverlayService } from 'app/core/ui-services/overlay.service';
|
||||||
import { UpdateService } from 'app/core/ui-services/update.service';
|
import { UpdateService } from 'app/core/ui-services/update.service';
|
||||||
import { DEFAULT_AUTH_TYPE } from 'app/shared/models/users/user';
|
|
||||||
import { AuthService } from '../core/core-services/auth.service';
|
|
||||||
import { BaseComponent } from '../base.component';
|
import { BaseComponent } from '../base.component';
|
||||||
import { MainMenuService } from '../core/core-services/main-menu.service';
|
import { MainMenuService } from '../core/core-services/main-menu.service';
|
||||||
import { OpenSlidesStatusService } from '../core/core-services/openslides-status.service';
|
import { OpenSlidesStatusService } from '../core/core-services/openslides-status.service';
|
||||||
@ -44,13 +41,6 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
@ViewChild('sideNav', { static: true })
|
@ViewChild('sideNav', { static: true })
|
||||||
public sideNav: MatSidenav;
|
public sideNav: MatSidenav;
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the username from the operator (should be known already)
|
|
||||||
*/
|
|
||||||
public username = '';
|
|
||||||
|
|
||||||
public authType = DEFAULT_AUTH_TYPE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is the user logged in, or the anonymous is active.
|
* is the user logged in, or the anonymous is active.
|
||||||
*/
|
*/
|
||||||
@ -76,12 +66,8 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
private delayedUpdateAvailable = false;
|
private delayedUpdateAvailable = false;
|
||||||
|
|
||||||
public samlChangePasswordUrl: string | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
|
||||||
* @param authService
|
|
||||||
* @param route
|
* @param route
|
||||||
* @param operator
|
* @param operator
|
||||||
* @param vp
|
* @param vp
|
||||||
@ -96,7 +82,6 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
protected translate: TranslateService,
|
protected translate: TranslateService,
|
||||||
offlineService: OfflineService,
|
offlineService: OfflineService,
|
||||||
private updateService: UpdateService,
|
private updateService: UpdateService,
|
||||||
private authService: AuthService,
|
|
||||||
private router: Router,
|
private router: Router,
|
||||||
public operator: OperatorService,
|
public operator: OperatorService,
|
||||||
public vp: ViewportService,
|
public vp: ViewportService,
|
||||||
@ -105,31 +90,15 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
public OSStatus: OpenSlidesStatusService,
|
public OSStatus: OpenSlidesStatusService,
|
||||||
public timeTravel: TimeTravelService,
|
public timeTravel: TimeTravelService,
|
||||||
private matSnackBar: MatSnackBar,
|
private matSnackBar: MatSnackBar,
|
||||||
private overlayService: OverlayService,
|
private overlayService: OverlayService
|
||||||
private loginDataService: LoginDataService
|
|
||||||
) {
|
) {
|
||||||
super(title, translate);
|
super(title, translate);
|
||||||
overlayService.showSpinner(translate.instant('Loading data. Please wait...'));
|
overlayService.showSpinner(translate.instant('Loading data. Please wait...'));
|
||||||
|
|
||||||
this.operator.getViewUserObservable().subscribe(user => {
|
|
||||||
if (!operator.isAnonymous) {
|
|
||||||
this.username = user ? user.short_name : '';
|
|
||||||
this.isLoggedIn = true;
|
|
||||||
} else {
|
|
||||||
this.username = translate.instant('Guest');
|
|
||||||
this.isLoggedIn = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.operator.authType.subscribe(authType => (this.authType = authType));
|
|
||||||
|
|
||||||
offlineService.isOffline().subscribe(offline => {
|
offlineService.isOffline().subscribe(offline => {
|
||||||
this.isOffline = offline;
|
this.isOffline = offline;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loginDataService.samlSettings.subscribe(
|
|
||||||
samlSettings => (this.samlChangePasswordUrl = samlSettings ? samlSettings.changePasswordUrl : null)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.searchform = new FormGroup({ query: new FormControl([]) });
|
this.searchform = new FormGroup({ query: new FormControl([]) });
|
||||||
|
|
||||||
// detect routing data such as base perm and noInterruption
|
// detect routing data such as base perm and noInterruption
|
||||||
@ -230,47 +199,6 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Let the user change the language
|
|
||||||
* @param lang the desired language (en, de, cs, ...)
|
|
||||||
*/
|
|
||||||
public selectLang(selection: string): void {
|
|
||||||
this.translate.use(selection).subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of a Language by abbreviation.
|
|
||||||
*
|
|
||||||
* @param abbreviation The abbreviation of the languate or null, if the current
|
|
||||||
* language should be used.
|
|
||||||
*/
|
|
||||||
public getLangName(abbreviation?: string): string {
|
|
||||||
if (!abbreviation) {
|
|
||||||
abbreviation = this.translate.currentLang;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abbreviation === 'en') {
|
|
||||||
return 'English';
|
|
||||||
} else if (abbreviation === 'de') {
|
|
||||||
return 'Deutsch';
|
|
||||||
} else if (abbreviation === 'cs') {
|
|
||||||
return 'Čeština';
|
|
||||||
} else if (abbreviation === 'ru') {
|
|
||||||
return 'русский';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to log out the current user
|
|
||||||
*/
|
|
||||||
public logout(): void {
|
|
||||||
if (this.operator.guestsEnabled) {
|
|
||||||
this.overlayService.showSpinner(null, true);
|
|
||||||
}
|
|
||||||
this.authService.logout();
|
|
||||||
this.overlayService.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle swipes and gestures
|
* Handle swipes and gestures
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
@import './app/shared/components/projector-button/projector-button.component.scss';
|
@import './app/shared/components/projector-button/projector-button.component.scss';
|
||||||
@import './app/site/agenda/components/list-of-speakers/list-of-speakers.component.scss-theme.scss';
|
@import './app/site/agenda/components/list-of-speakers/list-of-speakers.component.scss-theme.scss';
|
||||||
@import './app/shared/components/sorting-tree/sorting-tree.component.scss';
|
@import './app/shared/components/sorting-tree/sorting-tree.component.scss';
|
||||||
@import './app/site/common/components/global-spinner/global-spinner.component.scss';
|
@import './app/shared/components/global-spinner/global-spinner.component.scss';
|
||||||
@import './app/shared/components/tile/tile.component.scss';
|
@import './app/shared/components/tile/tile.component.scss';
|
||||||
@import './app/shared/components/block-tile/block-tile.component.scss';
|
@import './app/shared/components/block-tile/block-tile.component.scss';
|
||||||
@import './app/shared/components/icon-container/icon-container.component.scss';
|
@import './app/shared/components/icon-container/icon-container.component.scss';
|
||||||
|
@ -34,6 +34,15 @@ def get_config_variables():
|
|||||||
group="Participants",
|
group="Participants",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
yield ConfigVariable(
|
||||||
|
name="users_allow_self_set_present",
|
||||||
|
default_value=False,
|
||||||
|
input_type="boolean",
|
||||||
|
label="Allow users to set themselves as present",
|
||||||
|
weight=512,
|
||||||
|
group="Participants",
|
||||||
|
)
|
||||||
|
|
||||||
# PDF
|
# PDF
|
||||||
|
|
||||||
yield ConfigVariable(
|
yield ConfigVariable(
|
||||||
|
@ -9,6 +9,7 @@ urlpatterns = [
|
|||||||
url(r"^logout/$", views.UserLogoutView.as_view(), name="user_logout"),
|
url(r"^logout/$", views.UserLogoutView.as_view(), name="user_logout"),
|
||||||
url(r"^whoami/$", views.WhoAmIView.as_view(), name="user_whoami"),
|
url(r"^whoami/$", views.WhoAmIView.as_view(), name="user_whoami"),
|
||||||
url(r"^setpassword/$", views.SetPasswordView.as_view(), name="user_setpassword"),
|
url(r"^setpassword/$", views.SetPasswordView.as_view(), name="user_setpassword"),
|
||||||
|
url(r"^setpresence/$", views.SetPresenceView.as_view(), name="user_setpresence"),
|
||||||
url(
|
url(
|
||||||
r"^reset-password/$",
|
r"^reset-password/$",
|
||||||
views.PasswordResetView.as_view(),
|
views.PasswordResetView.as_view(),
|
||||||
|
@ -719,6 +719,23 @@ class PersonalNoteViewSet(ModelViewSet):
|
|||||||
# Special API views
|
# Special API views
|
||||||
|
|
||||||
|
|
||||||
|
class SetPresenceView(APIView):
|
||||||
|
http_method_names = ["post"]
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
user = request.user
|
||||||
|
if not config["users_allow_self_set_present"] or not user.is_authenticated:
|
||||||
|
raise ValidationError({"detail": "You cannot set your own presence"})
|
||||||
|
|
||||||
|
present = request.data
|
||||||
|
if present not in (True, False):
|
||||||
|
raise ValidationError({"detail": "Data must be a boolean"})
|
||||||
|
|
||||||
|
user.is_present = present
|
||||||
|
user.save()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
class WhoAmIDataView(APIView):
|
class WhoAmIDataView(APIView):
|
||||||
def get_whoami_data(self):
|
def get_whoami_data(self):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user