Adds a login handling to restrict the access to the i18n-manager route

parent 436a8951
Pipeline #16668 failed with stages
in 40 seconds
This diff is collapsed.
......@@ -22,8 +22,7 @@ export class FooterBarComponent implements OnInit, OnDestroy {
return this._footerElements;
}
@Input()
set footerElements(value: Array<IFooterBarElement>) {
@Input() set footerElements(value: Array<IFooterBarElement>) {
this.hasRightScrollElement = value.length > 1;
this._footerElements = value;
}
......@@ -126,7 +125,9 @@ export class FooterBarComponent implements OnInit, OnDestroy {
} else {
const child = navbarFooter.children.item(this.footerElemIndex);
const childWidth = child.clientWidth;
navbarFooter.scrollLeft -= (childWidth);
navbarFooter.scrollLeft -= (
childWidth
);
}
}
......@@ -146,7 +147,9 @@ export class FooterBarComponent implements OnInit, OnDestroy {
if (this.footerElemIndex === 1) {
const childWidth = child.clientWidth;
const leftButtonWidth = document.getElementById('footer-move-left').clientWidth;
navbarFooter.scrollLeft += (childWidth - leftButtonWidth);
navbarFooter.scrollLeft += (
childWidth - leftButtonWidth
);
} else {
navbarFooter.scrollLeft += child.clientWidth;
}
......@@ -158,6 +161,10 @@ export class FooterBarComponent implements OnInit, OnDestroy {
return;
}
if (!this.footerElements.length) {
return true;
}
const navbarFooter = document.getElementById('navbar-footer-container');
if (!navbarFooter) {
return false;
......
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { I18nManagerComponent } from './i18n-manager.component';
import { I18nManagerOverviewComponent } from './i18n-manager-overview.component';
describe('FeTranslationComponent', () => {
let component: I18nManagerComponent;
let fixture: ComponentFixture<I18nManagerComponent>;
describe('I18nManagerOverviewComponent', () => {
let component: I18nManagerOverviewComponent;
let fixture: ComponentFixture<I18nManagerOverviewComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [I18nManagerComponent],
declarations: [I18nManagerOverviewComponent],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(I18nManagerComponent);
fixture = TestBed.createComponent(I18nManagerOverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
......@@ -23,6 +23,6 @@ describe('FeTranslationComponent', () => {
expect(component).toBeTruthy();
});
it('should contain a TYPE reference', () => {
expect(I18nManagerComponent.TYPE).toEqual('I18nManagerComponent');
expect(I18nManagerOverviewComponent.TYPE).toEqual('I18nManagerOverviewComponent');
});
});
......@@ -3,18 +3,19 @@ import { Observable, of } from 'rxjs/index';
import { FooterBarService } from '../../service/footer-bar/footer-bar.service';
import { HeaderLabelService } from '../../service/header-label/header-label.service';
import { LanguageLoaderService } from '../../service/language-loader/language-loader.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { ModalOrganizerService } from '../../service/modal-organizer/modal-organizer.service';
import { ProjectLoaderService } from '../../service/project-loader/project-loader.service';
import { FILTER, PROJECT } from '../../shared/enums';
@Component({
selector: 'app-fe-translation',
templateUrl: './i18n-manager.component.html',
styleUrls: ['./i18n-manager.component.scss'],
selector: 'app-i18n-manager-overview',
templateUrl: './i18n-manager-overview.component.html',
styleUrls: ['./i18n-manager-overview.component.scss'],
})
export class I18nManagerComponent implements OnInit, OnDestroy {
export class I18nManagerOverviewComponent implements OnInit, OnDestroy {
public static readonly TYPE = 'I18nManagerComponent';
public static readonly TYPE = 'I18nManagerOverviewComponent';
public readonly filters = FILTER;
private _langRef = ['en', 'de', 'fr', 'it', 'es'];
......@@ -93,10 +94,15 @@ export class I18nManagerComponent implements OnInit, OnDestroy {
this._hasAnyMatches = value;
}
constructor(private footerBarService: FooterBarService, private headerLabelService: HeaderLabelService,
public modalOrganizerService: ModalOrganizerService, public projectLoaderService: ProjectLoaderService,
private languageLoaderService: LanguageLoaderService,
constructor(
private footerBarService: FooterBarService,
private headerLabelService: HeaderLabelService,
public modalOrganizerService: ModalOrganizerService,
public projectLoaderService: ProjectLoaderService,
private languageLoaderService: LanguageLoaderService,
private casService: CasLoginService,
) {
this.casService.casLoginRequired = true;
this.headerLabelService.headerLabel = 'I18Nator';
this.footerBarService.replaceFooterElements([]);
}
......
......@@ -2,16 +2,18 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PipesModule } from '../pipes/pipes.module';
import { LanguageLoaderService } from '../service/language-loader/language-loader.service';
import { StaticLoginService } from '../service/login/static-login.service';
import { ModalOrganizerService } from '../service/modal-organizer/modal-organizer.service';
import { ProjectLoaderService } from '../service/project-loader/project-loader.service';
import { SharedModule } from '../shared/shared.module';
import { I18nManagerComponent } from './i18n-manager/i18n-manager.component';
import { I18nManagerOverviewComponent } from './i18n-manager-overview/i18n-manager-overview.component';
import { KeyOutputComponent } from './key-output/key-output.component';
const i18nManagerRoutes: Routes = [
{
path: 'i18n-manager',
component: I18nManagerComponent,
canActivate: [StaticLoginService],
component: I18nManagerOverviewComponent,
},
];
......@@ -19,7 +21,7 @@ const i18nManagerRoutes: Routes = [
imports: [
SharedModule, PipesModule, RouterModule.forChild(i18nManagerRoutes),
],
declarations: [I18nManagerComponent, KeyOutputComponent],
declarations: [I18nManagerOverviewComponent, KeyOutputComponent],
providers: [
LanguageLoaderService, ProjectLoaderService, ModalOrganizerService,
],
......
......@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NgxQRCodeModule } from '@techiediaries/ngx-qrcode';
import { MarkdownModule } from '../../markdown/markdown.module';
import { CasService } from '../../service/cas/cas.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { SharedModule } from '../../shared/shared.module';
import { ThemesModule } from '../../themes/themes.module';
import { ConfidenceRateComponent } from './confidence-rate/confidence-rate.component';
......@@ -20,49 +20,40 @@ export const quizFlowRoutes: Routes = [
path: '',
pathMatch: 'full',
redirectTo: 'lobby',
},
{
}, {
path: 'lobby',
canLoad: [CasService],
canLoad: [CasLoginService],
component: QuizLobbyComponent,
data: {},
},
{
}, {
path: 'results',
component: QuizResultsComponent,
data: {},
},
{
}, {
path: 'results/:questionIndex',
component: QuestionDetailsComponent,
data: {},
},
{
}, {
path: 'theme',
component: QuizThemeComponent,
data: {},
},
{
}, {
path: 'leaderboard',
component: LeaderboardComponent,
data: {},
},
{
}, {
path: 'leaderboard/:questionIndex',
component: LeaderboardComponent,
data: {},
},
{
}, {
path: 'voting',
component: VotingComponent,
data: {},
},
{
}, {
path: 'reading-confirmation',
component: ReadingConfirmationComponent,
data: {},
},
{
}, {
path: 'confidence-rate',
component: ConfidenceRateComponent,
data: {},
......@@ -71,20 +62,10 @@ export const quizFlowRoutes: Routes = [
@NgModule({
imports: [
MarkdownModule,
SharedModule,
ThemesModule,
RouterModule.forChild(quizFlowRoutes),
QuizResultsModule,
NgxQRCodeModule,
MarkdownModule, SharedModule, ThemesModule, RouterModule.forChild(quizFlowRoutes), QuizResultsModule, NgxQRCodeModule,
],
declarations: [
QuizLobbyComponent,
VotingComponent,
LeaderboardComponent,
QuizThemeComponent,
ReadingConfirmationComponent,
ConfidenceRateComponent,
QuizLobbyComponent, VotingComponent, LeaderboardComponent, QuizThemeComponent, ReadingConfirmationComponent, ConfidenceRateComponent,
],
})
export class QuizFlowModule {
......
......@@ -4,8 +4,8 @@ import { questionGroupReflection } from 'arsnova-click-v2-types/src/questions/qu
import { Subscription } from 'rxjs';
import { LobbyApiService } from '../../service/api/lobby/lobby-api.service';
import { QuizApiService } from '../../service/api/quiz/quiz-api.service';
import { CasService } from '../../service/cas/cas.service';
import { CurrentQuizService } from '../../service/current-quiz/current-quiz.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { ThemesService } from '../../service/themes/themes.service';
@Component({
......@@ -22,7 +22,7 @@ export class QuizJoinComponent implements OnInit {
@Inject(PLATFORM_ID) private platformId: Object,
private route: ActivatedRoute,
private router: Router,
private casService: CasService,
private casService: CasLoginService,
public currentQuizService: CurrentQuizService,
private themesService: ThemesService,
private lobbyApiService: LobbyApiService,
......@@ -68,7 +68,12 @@ export class QuizJoinComponent implements OnInit {
this.router.navigate(['/nicks', 'memberGroup']);
} else {
this.router.navigate(['/nicks', (quizStatusData.payload.provideNickSelection ? 'select' : 'input')]);
this.router.navigate([
'/nicks',
(
quizStatusData.payload.provideNickSelection ? 'select' : 'input'
),
]);
}
}
......
......@@ -19,17 +19,18 @@ import { I18nManagerModule } from './i18n-manager/i18n-manager.module';
import { ModalsModule } from './modals/modals.module';
import { HomeComponent } from './root/home/home.component';
import { LanguageSwitcherComponent } from './root/language-switcher/language-switcher.component';
import { LoginComponent } from './root/login/login.component';
import { RootComponent } from './root/root/root.component';
import { ThemeSwitcherComponent } from './root/theme-switcher/theme-switcher.component';
import { ActiveQuestionGroupService } from './service/active-question-group/active-question-group.service';
import { AttendeeService } from './service/attendee/attendee.service';
import { CasService } from './service/cas/cas.service';
import { ConnectionService } from './service/connection/connection.service';
import { CurrentQuizService } from './service/current-quiz/current-quiz.service';
import { FileUploadService } from './service/file-upload/file-upload.service';
import { FooterBarService } from './service/footer-bar/footer-bar.service';
import { HeaderLabelService } from './service/header-label/header-label.service';
import { I18nService } from './service/i18n/i18n.service';
import { CasLoginService } from './service/login/cas-login.service';
import { SettingsService } from './service/settings/settings.service';
import { SharedService } from './service/shared/shared.service';
import { TrackingService } from './service/tracking/tracking.service';
......@@ -75,6 +76,9 @@ export const appRoutes: Routes = [
path: 'languages',
component: LanguageSwitcherComponent,
}, {
path: 'login',
component: LoginComponent,
}, {
path: '',
component: HomeComponent,
pathMatch: 'full',
......@@ -89,7 +93,7 @@ export const appRoutes: Routes = [
@NgModule({
declarations: [
HomeComponent, RootComponent, LanguageSwitcherComponent, ThemeSwitcherComponent,
HomeComponent, RootComponent, LanguageSwitcherComponent, ThemeSwitcherComponent, LoginComponent,
],
imports: [
BrowserModule.withServerTransition({ appId: 'frontend' }),
......@@ -137,7 +141,7 @@ export const appRoutes: Routes = [
CurrentQuizService,
TranslateModule,
UserService,
CasService,
CasLoginService,
FileUploadService,
SettingsService,
NgbActiveModal,
......
......@@ -13,7 +13,6 @@ import { ActiveQuestionGroupMockService } from '../../service/active-question-gr
import { ActiveQuestionGroupService } from '../../service/active-question-group/active-question-group.service';
import { AttendeeMockService } from '../../service/attendee/attendee.mock.service';
import { AttendeeService } from '../../service/attendee/attendee.service';
import { CasService } from '../../service/cas/cas.service';
import { ConnectionMockService } from '../../service/connection/connection.mock.service';
import { ConnectionService } from '../../service/connection/connection.service';
import { CurrentQuizMockService } from '../../service/current-quiz/current-quiz.mock.service';
......@@ -23,6 +22,7 @@ import { FileUploadService } from '../../service/file-upload/file-upload.service
import { FooterBarService } from '../../service/footer-bar/footer-bar.service';
import { HeaderLabelService } from '../../service/header-label/header-label.service';
import { I18nService } from '../../service/i18n/i18n.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { SettingsMockService } from '../../service/settings/settings.mock.service';
import { SettingsService } from '../../service/settings/settings.service';
import { SharedService } from '../../service/shared/shared.service';
......@@ -43,57 +43,85 @@ describe('HomeComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule,
HttpClientModule,
HttpClientTestingModule,
TranslateModule.forRoot({
RouterTestingModule, HttpClientModule, HttpClientTestingModule, TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
useFactory: (
createTranslateLoader
),
deps: [HttpClient],
},
compiler: {
provide: TranslateCompiler,
useClass: TranslateMessageFormatCompiler,
},
}),
ModalsModule,
NgbModule.forRoot(),
}), ModalsModule, NgbModule.forRoot(),
],
providers: [
FooterBarService,
{ provide: SettingsService, useClass: SettingsMockService },
{ provide: ConnectionService, useClass: ConnectionMockService },
{ provide: WebsocketService, useClass: WebsocketMockService },
{
provide: SettingsService,
useClass: SettingsMockService,
},
{
provide: ConnectionService,
useClass: ConnectionMockService,
},
{
provide: WebsocketService,
useClass: WebsocketMockService,
},
SharedService,
HeaderLabelService,
{ provide: ActiveQuestionGroupService, useClass: ActiveQuestionGroupMockService },
{ provide: ThemesService, useClass: ThemesMockService },
{
provide: ActiveQuestionGroupService,
useClass: ActiveQuestionGroupMockService,
},
{
provide: ThemesService,
useClass: ThemesMockService,
},
I18nService,
{ provide: AttendeeService, useClass: AttendeeMockService },
CasService,
{
provide: AttendeeService,
useClass: AttendeeMockService,
},
CasLoginService,
UserService,
{ provide: TrackingService, useClass: TrackingMockService },
{ provide: CurrentQuizService, useClass: CurrentQuizMockService },
{ provide: FileUploadService, useClass: FileUploadMockService },
{
provide: TrackingService,
useClass: TrackingMockService,
},
{
provide: CurrentQuizService,
useClass: CurrentQuizMockService,
},
{
provide: FileUploadService,
useClass: FileUploadMockService,
},
],
declarations: [HomeComponent],
}).compileComponents();
});
beforeEach((() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
beforeEach((
() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}
));
it('should be created', () => {
expect(component).toBeTruthy();
});
it('should contain a TYPE reference', (() => {
expect(HomeComponent.TYPE).toEqual('HomeComponent');
}));
it('should contain a TYPE reference', (
() => {
expect(HomeComponent.TYPE).toEqual('HomeComponent');
}
));
it('should render \'arsnova.click\' in the main view', () => {
const compiled = fixture.debugElement.nativeElement;
......@@ -116,14 +144,12 @@ describe('HomeComponent', () => {
describe('#autoJoinToSession', () => {
it('should join the session by click', async(inject(
[Router], (router: Router) => {
spyOn(component, 'selectQuizByList').and.callThrough();
spyOn(router, 'navigate').and.callFake(() => {});
it('should join the session by click', async(inject([Router], (router: Router) => {
spyOn(component, 'selectQuizByList').and.callThrough();
spyOn(router, 'navigate').and.callFake(() => {});
component.autoJoinToSession('testquiz');
expect(component.selectQuizByList).toHaveBeenCalled();
}),
));
component.autoJoinToSession('testquiz');
expect(component.selectQuizByList).toHaveBeenCalled();
})));
});
});
......@@ -16,12 +16,12 @@ import { ActiveQuestionGroupService } from '../../service/active-question-group/
import { LobbyApiService } from '../../service/api/lobby/lobby-api.service';
import { QuizApiService } from '../../service/api/quiz/quiz-api.service';
import { AttendeeService } from '../../service/attendee/attendee.service';
import { CasService } from '../../service/cas/cas.service';
import { ConnectionService } from '../../service/connection/connection.service';
import { CurrentQuizService } from '../../service/current-quiz/current-quiz.service';
import { FooterBarService } from '../../service/footer-bar/footer-bar.service';
import { HeaderLabelService } from '../../service/header-label/header-label.service';
import { I18nService, Languages } from '../../service/i18n/i18n.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { SettingsService } from '../../service/settings/settings.service';
import { SharedService } from '../../service/shared/shared.service';
import { ThemesService } from '../../service/themes/themes.service';
......@@ -78,26 +78,25 @@ export class HomeComponent implements OnInit, OnDestroy {
private readonly _routerSubscription: Subscription;
private readonly _ownQuizzes: Array<string> = [];
constructor(
@Inject(PLATFORM_ID) private platformId: Object,
private footerBarService: FooterBarService,
private headerLabelService: HeaderLabelService,
private modalService: NgbModal,
private activeQuestionGroupService: ActiveQuestionGroupService,
private currentQuizService: CurrentQuizService,
private router: Router,
private themesService: ThemesService,
private route: ActivatedRoute,
private i18nService: I18nService,
private attendeeService: AttendeeService,
private connectionService: ConnectionService,
private sanitizer: DomSanitizer,
private casService: CasService,
private settingsService: SettingsService,
private trackingService: TrackingService,
private quizApiService: QuizApiService,
private lobbyApiService: LobbyApiService,
public sharedService: SharedService,
constructor(@Inject(PLATFORM_ID) private platformId: Object,
private footerBarService: FooterBarService,
private headerLabelService: HeaderLabelService,
private modalService: NgbModal,
private activeQuestionGroupService: ActiveQuestionGroupService,
private currentQuizService: CurrentQuizService,
private router: Router,
private themesService: ThemesService,
private route: ActivatedRoute,
private i18nService: I18nService,
private attendeeService: AttendeeService,
private connectionService: ConnectionService,
private sanitizer: DomSanitizer,
private casService: CasLoginService,
private settingsService: SettingsService,
private trackingService: TrackingService,
private quizApiService: QuizApiService,
private lobbyApiService: LobbyApiService,
public sharedService: SharedService,
) {
this.footerBarService.TYPE_REFERENCE = HomeComponent.TYPE;
......@@ -140,20 +139,18 @@ export class HomeComponent implements OnInit, OnDestroy {
this.connectionService.initConnection().then(() => {
this.connectionService.socket.subscribe(data => {
console.log(data);
this.connectionService.websocketAvailable = true;
switch (data.step) {
case 'QUIZ:SET_ACTIVE':
this.sharedService.activeQuizzes.push(data.payload.quizName);
break;
case 'QUIZ:SET_INACTIVE':
const index = this.sharedService.activeQuizzes.findIndex(name => name === data.payload.quizName);
this.sharedService.activeQuizzes.splice(index, 1);
}
},
() => this.connectionService.websocketAvailable = false,
);
console.log(data);
this.connectionService.websocketAvailable = true;
switch (data.step) {
case 'QUIZ:SET_ACTIVE':
this.sharedService.activeQuizzes.push(data.payload.quizName);
break;
case 'QUIZ:SET_INACTIVE':
const index = this.sharedService.activeQuizzes.findIndex(name => name === data.payload.quizName);
this.sharedService.activeQuizzes.splice(index, 1);
}
}, () => this.connectionService.websocketAvailable = false);
});
}
......@@ -208,7 +205,9 @@ export class HomeComponent implements OnInit, OnDestroy {
}
public setPassword(event: Event): void {
this._serverPassword = (<HTMLInputElement>event.target).value;
this._serverPassword = (
<HTMLInputElement>event.target
).value;
}
public handleClick(id: string): boolean {
......@@ -247,15 +246,10 @@ export class HomeComponent implements OnInit, OnDestroy {
public setActiveQuestionGroup(routingTarget?: Array<string>): boolean {
if (isPlatformBrowser(this.platformId)) {
const questionGroupSerialized = JSON.parse(
localStorage.getItem(
Object.keys(localStorage).find(name => name.toLowerCase() === this.enteredSessionName.toLowerCase()),
),
);
localStorage.getItem(Object.keys(localStorage).find(name => name.toLowerCase() === this.enteredSessionName.toLowerCase())));
if (questionGroupSerialized) {
this.activeQuestionGroupService.activeQuestionGroup = questionGroupReflection[questionGroupSerialized.TYPE](
questionGroupSerialized,
);
this.activeQuestionGroupService.activeQuestionGroup = questionGroupReflection[questionGroupSerialized.TYPE](questionGroupSerialized);
}
}
......@@ -272,12 +266,11 @@ export class HomeComponent implements OnInit, OnDestroy {
}
const questionGroupSerialized = JSON.parse(
localStorage.getItem(
Object.keys(localStorage).find(name => name.toLowerCase() === this.enteredSessionName.toLowerCase()),
),
);
localStorage.getItem(Object.keys(localStorage).find(name => name.toLowerCase() === this.enteredSessionName.toLowerCase())));
if (this.passwordRequired && !(this._serverPassword && this._serverPassword.length)) {
if (this.passwordRequired && !(
this._serverPassword && this._serverPassword.length
)) {
return;
}
......@@ -318,9 +311,15 @@ export class HomeComponent implements OnInit, OnDestroy {
this.currentQuizService.persistToSessionStorage();
if (this.isAddingABCDQuiz) {
this.trackingService.trackConversionEvent({ action: HomeComponent.TYPE, label: 'ABCD Quiz created' });
this.trackingService.trackConversionEvent({
action: HomeComponent.TYPE,
label: 'ABCD Quiz created',
});
} else if (this.isAddingDemoQuiz) {
this.trackingService.trackConversionEvent({ action: HomeComponent.TYPE, label: 'Demo Quiz created' });
this.trackingService.trackConversionEvent({
action: HomeComponent.TYPE,
label: 'Demo Quiz created',
});
}
await this.activateQuiz(questionGroup);
......@@ -481,14 +480,24 @@ export class HomeComponent implements OnInit, OnDestroy {
if (hasMatchedABCDQuiz.length) {
const rawQuiz = JSON.parse(window.localStorage.getItem(hasMatchedABCDQuiz[0]));
const questionGroup = questionGroupReflection.DefaultQuestionGroup(rawQuiz);
const answerOptionList = (<Array<DefaultAnswerOption>>[]);
const answerOptionList = (
<Array<DefaultAnswerOption>>[]
);
answerList.forEach((character, index) => {
answerOptionList.push(new DefaultAnswerOption({ answerText: (String.fromCharCode(index + 65)) }));