Merge pull request #3815 from tsiegleauq/MobileObserveService
ViewportService and new Prefix
This commit is contained in:
commit
cbf8a33b8d
@ -1,13 +1,13 @@
|
||||
{
|
||||
"/users/login": {
|
||||
"/apps/users/login": {
|
||||
"target": "http://localhost:8000",
|
||||
"secure": false
|
||||
},
|
||||
"/users/logout": {
|
||||
"/apps/users/logout": {
|
||||
"target": "http://localhost:8000",
|
||||
"secure": false
|
||||
},
|
||||
"/users/whoami": {
|
||||
"/apps/users/whoami": {
|
||||
"target": "http://localhost:8000",
|
||||
"secure": false
|
||||
},
|
||||
|
@ -12,6 +12,7 @@ import { OperatorService } from './services/operator.service';
|
||||
import { WebsocketService } from './services/websocket.service';
|
||||
import { AddHeaderInterceptor } from './http-interceptor';
|
||||
import { DataSendService } from './services/data-send.service';
|
||||
import { ViewportService } from './services/viewport.service';
|
||||
|
||||
/** Global Core Module. Contains all global (singleton) services
|
||||
*
|
||||
@ -26,6 +27,7 @@ import { DataSendService } from './services/data-send.service';
|
||||
DataStoreService,
|
||||
DataSendService,
|
||||
OperatorService,
|
||||
ViewportService,
|
||||
WebsocketService,
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
|
@ -5,6 +5,7 @@ import { catchError, tap } from 'rxjs/operators';
|
||||
|
||||
import { OperatorService } from 'app/core/services/operator.service';
|
||||
import { OpenSlidesComponent } from '../../openslides.component';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
/**
|
||||
* Authenticates an OpenSlides user with username and password
|
||||
@ -44,7 +45,7 @@ export class AuthService extends OpenSlidesComponent {
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
return this.http.post<any>('/users/login/', user).pipe(
|
||||
return this.http.post<any>(environment.urlPrefix + '/users/login/', user).pipe(
|
||||
tap(resp => this.operator.storeUser(resp.user)),
|
||||
catchError(this.handleError())
|
||||
);
|
||||
@ -60,6 +61,6 @@ export class AuthService extends OpenSlidesComponent {
|
||||
//TODO not yet used
|
||||
logout(): Observable<any> {
|
||||
this.operator.clear();
|
||||
return this.http.post<any>('/users/logout/', {});
|
||||
return this.http.post<any>(environment.urlPrefix + '/users/logout/', {});
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { tap, catchError, share } from 'rxjs/operators';
|
||||
import { OpenSlidesComponent } from 'app/openslides.component';
|
||||
import { Group } from 'app/shared/models/users/group';
|
||||
import { User } from '../../shared/models/users/user';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
/**
|
||||
* The operator represents the user who is using OpenSlides.
|
||||
@ -74,10 +75,10 @@ export class OperatorService extends OpenSlidesComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* calls `/users/whoami` to find out the real operator
|
||||
* calls `/apps/users/whoami` to find out the real operator
|
||||
*/
|
||||
public whoAmI(): Observable<any> {
|
||||
return this.http.get<any>('/users/whoami/').pipe(
|
||||
return this.http.get<any>(environment.urlPrefix + '/users/whoami/').pipe(
|
||||
tap(whoami => {
|
||||
if (whoami && whoami.user) {
|
||||
this.storeUser(whoami.user as User);
|
||||
|
15
client/src/app/core/services/viewport.service.spec.ts
Normal file
15
client/src/app/core/services/viewport.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { ViewportService } from './viewport.service';
|
||||
|
||||
describe('ViewportService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [ViewportService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([ViewportService], (service: ViewportService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
30
client/src/app/core/services/viewport.service.ts
Normal file
30
client/src/app/core/services/viewport.service.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ViewportService {
|
||||
/**
|
||||
* True if Viewport equals mobile or small resolution.
|
||||
*/
|
||||
private _isMobile = false;
|
||||
|
||||
constructor(private breakpointObserver: BreakpointObserver) {}
|
||||
|
||||
checkForChange() {
|
||||
this.breakpointObserver
|
||||
.observe([Breakpoints.Small, Breakpoints.HandsetPortrait])
|
||||
.subscribe((state: BreakpointState) => {
|
||||
if (state.matches) {
|
||||
this._isMobile = true;
|
||||
} else {
|
||||
this._isMobile = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get isMobile() {
|
||||
return this._isMobile;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<mat-sidenav-container autosize class='main-container'>
|
||||
<mat-sidenav #sideNav [mode]="isMobile ? 'push' : 'side'" [opened]='!isMobile' disableClose='!isMobile' class="side-panel">
|
||||
<mat-sidenav #sideNav [mode]="vp.isMobile ? 'push' : 'side'" [opened]='!vp.isMobile' disableClose='!vp.isMobile' class="side-panel">
|
||||
<mat-toolbar class='nav-toolbar'>
|
||||
<!-- logo -->
|
||||
<mat-toolbar-row class='os-logo-container'>
|
||||
@ -42,39 +42,39 @@
|
||||
<!-- navigation -->
|
||||
<mat-nav-list class='main-nav'>
|
||||
<a [@navItemAnim] *appOsPerms="['core.can_see_frontpage']" mat-list-item routerLink='/' routerLinkActive='active' [routerLinkActiveOptions]="{exact: true}"
|
||||
(click)='isMobile ? sideNav.toggle() : null'>
|
||||
(click)='toggleSideNav()'>
|
||||
<fa-icon icon='home'></fa-icon>
|
||||
<span translate>Home</span>
|
||||
</a>
|
||||
<a [@navItemAnim] *appOsPerms="['agenda.can_see']" mat-list-item routerLink='/agenda' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
|
||||
<a [@navItemAnim] *appOsPerms="['agenda.can_see']" mat-list-item routerLink='/agenda' routerLinkActive='active' (click)='toggleSideNav()'>
|
||||
<fa-icon icon='calendar'></fa-icon>
|
||||
<span translate>Agenda</span>
|
||||
</a>
|
||||
<a [@navItemAnim] *appOsPerms="['motions.can_see']" mat-list-item routerLink='/motions' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
|
||||
<a [@navItemAnim] *appOsPerms="['motions.can_see']" mat-list-item routerLink='/motions' routerLinkActive='active' (click)='toggleSideNav()'>
|
||||
<fa-icon icon='file-alt'></fa-icon>
|
||||
<span translate>Motions</span>
|
||||
</a>
|
||||
<a [@navItemAnim] *appOsPerms="['assignments.can_see']" mat-list-item routerLink='/assignments' routerLinkActive='active'
|
||||
(click)='isMobile ? sideNav.toggle() : null'>
|
||||
(click)='vp.isMobile ? sideNav.toggle() : null'>
|
||||
<fa-icon icon='chart-pie'></fa-icon>
|
||||
<span translate>Assignments</span>
|
||||
</a>
|
||||
<a [@navItemAnim] *appOsPerms="['users.can_see_name']" mat-list-item routerLink='/users' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
|
||||
<a [@navItemAnim] *appOsPerms="['users.can_see_name']" mat-list-item routerLink='/users' routerLinkActive='active' (click)='toggleSideNav()'>
|
||||
<fa-icon icon='user'></fa-icon>
|
||||
<span translate>Participants</span>
|
||||
</a>
|
||||
<a [@navItemAnim] *appOsPerms="['mediafiles.can_see']" mat-list-item routerLink='/mediafiles' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
|
||||
<a [@navItemAnim] *appOsPerms="['mediafiles.can_see']" mat-list-item routerLink='/mediafiles' routerLinkActive='active' (click)='toggleSideNav()'>
|
||||
<fa-icon icon='paperclip'></fa-icon>
|
||||
<span translate>Files</span>
|
||||
</a>
|
||||
<a [@navItemAnim] *appOsPerms="['core.can_manage_config']" mat-list-item routerLink='/settings' routerLinkActive='active'
|
||||
(click)='isMobile ? sideNav.toggle() : null'>
|
||||
(click)='toggleSideNav()'>
|
||||
<fa-icon icon='cog'></fa-icon>
|
||||
<span translate>Settings</span>
|
||||
</a>
|
||||
<mat-divider></mat-divider>
|
||||
<a [@navItemAnim] *appOsPerms="['core.can_see_projector']" mat-list-item routerLink='/projector' routerLinkActive='active'
|
||||
(click)='isMobile ? sideNav.toggle() : null'>
|
||||
(click)='toggleSideNav()'>
|
||||
<fa-icon icon='video'></fa-icon>
|
||||
<span translate>Projector</span>
|
||||
</a>
|
||||
@ -83,18 +83,15 @@
|
||||
|
||||
<footer>
|
||||
<button mat-button>
|
||||
<a routerLink='/legalnotice' (click)='isMobile ? sideNav.toggle() : null'>
|
||||
<a routerLink='/legalnotice' (click)='toggleSideNav()'>
|
||||
<span translate>Legal Notice</span>
|
||||
</a>
|
||||
</button>
|
||||
<button mat-button>
|
||||
<a routerLink='/privacypolicy' (click)='isMobile ? sideNav.toggle() : null'>
|
||||
<a routerLink='/privacypolicy' (click)='toggleSideNav()'>
|
||||
<span translate>Privacy Policy</span>
|
||||
</a>
|
||||
</button>
|
||||
<!-- <button mat-button (click)='openPrivacyPolicy()'>
|
||||
<span translate>Privacy Policy</span>
|
||||
</button> -->
|
||||
<br>
|
||||
<span align="center">© Copyright by
|
||||
<a href='https://openslides.org/'>OpenSlides</a>
|
||||
@ -107,7 +104,7 @@
|
||||
<mat-toolbar color='primary'>
|
||||
|
||||
<!-- show/hide menu button -->
|
||||
<button mat-icon-button *ngIf="isMobile" (click)='sideNav.toggle()'>
|
||||
<button mat-icon-button *ngIf="vp.isMobile" (click)='sideNav.toggle()'>
|
||||
<fa-icon icon='bars'></fa-icon>
|
||||
</button>
|
||||
|
||||
@ -122,4 +119,4 @@
|
||||
<main [@pageTransition]="o.isActivated ? o.activatedRoute : ''">
|
||||
<router-outlet #o="outlet"></router-outlet>
|
||||
</main>
|
||||
</mat-sidenav-container>
|
||||
</mat-sidenav-container>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||
import { Component, OnInit, HostBinding, ViewChild } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
|
||||
|
||||
@ -9,7 +9,8 @@ import { OperatorService } from 'app/core/services/operator.service';
|
||||
import { TranslateService } from '@ngx-translate/core'; //showcase
|
||||
import { BaseComponent } from 'app/base.component';
|
||||
import { pageTransition, navItemAnim } from 'app/shared/animations';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { MatDialog, MatSidenav } from '@angular/material';
|
||||
import { ViewportService } from '../core/services/viewport.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-site',
|
||||
@ -18,16 +19,16 @@ import { MatDialog } from '@angular/material';
|
||||
styleUrls: ['./site.component.scss']
|
||||
})
|
||||
export class SiteComponent extends BaseComponent implements OnInit {
|
||||
/**
|
||||
* HTML element of the side panel
|
||||
*/
|
||||
@ViewChild('sideNav') sideNav: MatSidenav;
|
||||
|
||||
/**
|
||||
* Get the username from the operator (should be known already)
|
||||
*/
|
||||
username = this.operator.username;
|
||||
|
||||
/**
|
||||
* True if Viewport equals mobile or small resolution. Set by breakpointObserver.
|
||||
*/
|
||||
isMobile = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -44,7 +45,7 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
||||
private autoupdateService: AutoupdateService,
|
||||
private operator: OperatorService,
|
||||
private router: Router,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
public vp: ViewportService,
|
||||
public translate: TranslateService,
|
||||
public dialog: MatDialog
|
||||
) {
|
||||
@ -55,15 +56,7 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
||||
* Initialize the site component
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.breakpointObserver
|
||||
.observe([Breakpoints.Small, Breakpoints.HandsetPortrait])
|
||||
.subscribe((state: BreakpointState) => {
|
||||
if (state.matches) {
|
||||
this.isMobile = true;
|
||||
} else {
|
||||
this.isMobile = false;
|
||||
}
|
||||
});
|
||||
this.vp.checkForChange();
|
||||
|
||||
// get a translation via code: use the translation service
|
||||
// this.translate.get('Motions').subscribe((res: string) => {
|
||||
@ -82,6 +75,15 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the sidenav in mobile view
|
||||
*/
|
||||
toggleSideNav() {
|
||||
if (this.vp.isMobile) {
|
||||
this.sideNav.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the user change the language
|
||||
* @param lang the desired language (en, de, fr, ...)
|
||||
|
@ -3,7 +3,8 @@
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
production: false
|
||||
production: false,
|
||||
urlPrefix: '/apps'
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user