Commit ada125b8 authored by Konstantin Schulz's avatar Konstantin Schulz
Browse files

introducing the test module and enabling language change at runtime

parent dce15f9c
......@@ -10,9 +10,14 @@ Make sure to assign at least 4GB RAM (Memory) to the Docker container, otherwise
5. Run `docker-compose up -d` and enjoy!
----------------------------------------------------------------
##### Access to the Docker container
##### Build
If you don't want to use Docker for building, you need to run `npm install` first.
To build the application for production environments, use: `ionic cordova build browser --prod --release --max-old-space-size=4096` and serve the content of the `www/` folder, e.g. with Nginx.
----------------------------------------------------------------
##### Extending the application
To add new pages to the application, use: `ionic generate page PAGE_NAME`.
----------------------------------------------------------------
##### Access to the Docker container
Use `docker-compose down` to stop and remove the currently running containers.
......
This diff is collapsed.
{
"name": "mc_frontend",
"version": "0.7.2",
"version": "0.7.5",
"author": "Ionic Framework",
"homepage": "https://ionicframework.com/",
"scripts": {
......@@ -13,13 +13,13 @@
},
"private": true,
"dependencies": {
"@angular/common": "^7.2.2",
"@angular/core": "^7.2.2",
"@angular/forms": "^7.2.2",
"@angular/http": "^7.2.2",
"@angular/platform-browser": "^7.2.2",
"@angular/platform-browser-dynamic": "^7.2.2",
"@angular/router": "^7.2.2",
"@angular/common": "^7.2.10",
"@angular/core": "^7.2.10",
"@angular/forms": "^7.2.10",
"@angular/http": "^7.2.10",
"@angular/platform-browser": "^7.2.10",
"@angular/platform-browser-dynamic": "^7.2.10",
"@angular/router": "^7.2.10",
"@ionic-native/core": "^5.0.0",
"@ionic-native/splash-screen": "^5.0.0",
"@ionic-native/status-bar": "^5.0.0",
......@@ -41,11 +41,11 @@
},
"devDependencies": {
"@angular-devkit/architect": "~0.12.3",
"@angular-devkit/build-angular": "^0.13.6",
"@angular-devkit/build-angular": "^0.13.8",
"@angular-devkit/core": "~7.2.3",
"@angular-devkit/schematics": "~7.2.3",
"@angular/cli": "~7.2.3",
"@angular/compiler": "~7.2.2",
"@angular/compiler": "^7.2.10",
"@angular/compiler-cli": "^7.2.10",
"@angular/language-service": "~7.2.2",
"@ionic/angular-toolkit": "^1.3.0",
......@@ -80,4 +80,4 @@
"cordova-plugin-splashscreen": {}
}
}
}
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ const routes: Routes = [
{ path: 'kwic', loadChildren: './kwic/kwic.module#KwicPageModule' },
{ path: 'ranking', loadChildren: './ranking/ranking.module#RankingPageModule' },
{ path: 'feedback', loadChildren: './feedback/feedback.module#FeedbackPageModule' },
{ path: 'change-language', loadChildren: './change-language/change-language.module#ChangeLanguagePageModule' },
];
@NgModule({
......
......@@ -37,7 +37,7 @@ export class AppComponent {
} else {
this.translate.use(this.translate.getDefaultLang()); // Set your language here
}
// TODO: DELETE THIS
// for testing purposes
// this.translate.use('de');
// this.translate.get(['BACK_BUTTON_TEXT']).subscribe(values => {
......
......@@ -9,18 +9,14 @@ import {StatusBar} from '@ionic-native/status-bar/ngx';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from 'src/app/app.component';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
// The translate loader needs to know where to load i18n files
// in Ionic's static asset pipeline.
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
import {ChangeLanguagePage} from "src/app/change-language/change-language.page";
import {ChangeLanguagePageModule} from "src/app/change-language/change-language.module";
import {HelperService} from "src/app/helper.service";
@NgModule({
declarations: [AppComponent],
entryComponents: [],
entryComponents: [ChangeLanguagePage],
imports: [
BrowserModule,
IonicModule.forRoot(),
......@@ -29,10 +25,11 @@ export function createTranslateLoader(http: HttpClient) {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
useFactory: (HelperService.createTranslateLoader),
deps: [HttpClient]
}
}),
ChangeLanguagePageModule
],
providers: [
StatusBar,
......
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {Routes, RouterModule} from '@angular/router';
import {IonicModule} from '@ionic/angular';
import {ChangeLanguagePage} from './change-language.page';
import {TranslateLoader, TranslateModule} from "@ngx-translate/core";
import {HttpClient} from "@angular/common/http";
import {HelperService} from "src/app/helper.service";
const routes: Routes = [
{
path: '',
component: ChangeLanguagePage
}
];
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild(routes),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: (HelperService.createTranslateLoader),
deps: [HttpClient]
}
}),
],
declarations: [ChangeLanguagePage]
})
export class ChangeLanguagePageModule {
}
<ion-header>
<ion-toolbar>
<ion-title>{{ 'LANGUAGE_CHANGE' | translate }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-grid>
<ion-row>
<ion-col>
<button (click)="changeLanguage('en')">
<img src="assets/imgs/en.svg" width="80px" height="48px">
</button>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<button (click)="changeLanguage('de')">
<img src="assets/imgs/de.svg" width="80px" height="48px">
</button>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChangeLanguagePage } from './change-language.page';
describe('ChangeLanguagePage', () => {
let component: ChangeLanguagePage;
let fixture: ComponentFixture<ChangeLanguagePage>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChangeLanguagePage ],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChangeLanguagePage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, OnInit} from '@angular/core';
import {TranslateService} from "@ngx-translate/core";
@Component({
selector: 'app-change-language',
templateUrl: './change-language.page.html',
styleUrls: ['./change-language.page.scss'],
})
export class ChangeLanguagePage implements OnInit {
constructor(public translate: TranslateService) {
}
changeLanguage(newLanguage: string) {
if (this.translate.currentLang !== newLanguage) {
this.translate.use(newLanguage);
}
}
ngOnInit() {
}
}
......@@ -16,6 +16,29 @@
<ion-content padding>
<ion-grid>
<!--<ion-row>-->
<!--<ion-col>{{ 'TEST_MODULE_GO_TO_EXERCISE' | translate}}-->
<!--&lt;!&ndash;suppress HtmlUnknownAttribute &ndash;&gt;-->
<!--<ion-select placeholder="{{ 'TEST_MODULE_EXERCISE_NUMBER' | translate }}" (ionChange)="goToExercise()"-->
<!--[(ngModel)]="newExerciseTarget" name="newExerciseTarget">-->
<!--<ion-select-option-->
<!--*ngFor="let number of Array.from(Array(exercises.length).keys())"-->
<!--value="{{number}}">{{number + 1}}</ion-select-option>-->
<!--</ion-select>-->
<!--</ion-col>-->
<!--</ion-row>-->
<!--<ion-row>-->
<!--<ion-col>-->
<!--&lt;!&ndash; TODO: enable solution shuffling for H5P ? &ndash;&gt;-->
<!--<div class="h5p-container"></div>-->
<!--</ion-col>-->
<!--</ion-row>-->
<!--<ion-row>-->
<!--<ion-col *ngIf="this.exercises.indexOf(this.currentExercise) < this.exercises.length - 1">-->
<!--<ion-button (click)="showNextExercise(this.exercises.indexOf(this.currentExercise) + 1)">Weiter-->
<!--</ion-button>-->
<!--</ion-col>-->
<!--</ion-row>-->
<ion-row>
<ion-col>
<h1>{{ 'HELP' | translate }}</h1>
......@@ -49,6 +72,7 @@
</ion-row>
<ion-row>
<ion-col>
<!--suppress HtmlUnknownTarget -->
<a href="{{HelperService.config['developerMailTo']}}">{{ 'EMAIL' | translate }}</a>
</ion-col>
</ion-row>
......
import {Component} from '@angular/core';
import {NavController, NavParams} from "@ionic/angular";
import {NavController} from "@ionic/angular";
import {HelperService} from '../helper.service';
import {XAPIevent} from "src/app/models/xAPIevent";
import {TranslateService} from "@ngx-translate/core";
declare var H5P: any;
// dirty hack to prevent H5P access errors after resize events
window.onresize = () => {
/* tslint:disable:prefer-const */
/* tslint:disable:no-shadowed-variable */
let H5P: any;
/* tslint:enable:prefer-const */
/* tslint:enable:no-shadowed-variable */
};
@Component({
selector: 'app-feedback',
......@@ -8,9 +20,50 @@ import {HelperService} from '../helper.service';
styleUrls: ['./feedback.page.scss'],
})
export class FeedbackPage {
Array = Array;
HelperService = HelperService;
public currentExercise: string = "";
public exercises: string[] = ["fill_blanks_1", "multi_choice_1", "multi_choice_2", "multi_choice_3", "multi_choice_4", "multi_choice_5", "multi_choice_6", "multi_choice_7", "multi_choice_8", "fill_blanks_2", "fill_blanks_3", "fill_blanks_4", "fill_blanks_5", "multi_choice_9", "fill_blanks_6", "multi_choice_10", "multi_choice_11", "multi_choice_12", "multi_choice_13"];
public newExerciseTarget: number;
constructor(public navCtrl: NavController, public translate: TranslateService) {
this.showNextExercise(0);
}
goToExercise() {
this.showNextExercise(this.newExerciseTarget);
}
public initH5P(exerciseType: string) {
// dirty hack to get H5P going without explicit button click on the new page
setTimeout(() => {
(($) => {
$(() => {
// $('.h5p-container').empty();
$('.h5p-container').empty().h5p({
frameJs: 'assets/dist/js/h5p-standalone-frame.min.js',
frameCss: 'assets/dist/styles/h5p.css',
h5pContent: 'assets/test_module/' + exerciseType
});
});
})(H5P.jQuery);
H5P.externalDispatcher.on('xAPI', (event: XAPIevent) => {
// results are only available when a task has been completed/answered, not in the "attempted" or "interacted" stages
if (event.data.statement.verb.id === HelperService.config["xAPIverbIDanswered"] && event.data.statement.result) {
// TODO: SAVE THIS SCORE BY SENDING IT TO THE BACKEND? OR WRITE THE WHOLE STATEMENT?
// console.log(event.data.statement.result.score.scaled);
}
});
}, 50);
}
constructor(public navCtrl: NavController) {
showNextExercise(newIndex: number) {
this.currentExercise = this.exercises[newIndex];
let fileName: string = this.currentExercise.split("_").slice(-1) + "_" + this.translate.currentLang + ".json";
const exerciseType = this.currentExercise.split("_").slice(0, 2).join("_");
const baseUrl: string = location.protocol.concat('//').concat(window.location.host);
window.localStorage.setItem(HelperService.config['localStorageKeyH5P'], baseUrl + "/assets/test_module/" + exerciseType + "/content/" + fileName);
this.initH5P(exerciseType);
}
openUrl(url: string) {
......
......@@ -2,6 +2,7 @@ import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {NavController} from '@ionic/angular';
import {ApplicationState} from 'src/app/models/applicationState';
import {TranslateHttpLoader} from "@ngx-translate/http-loader";
@Injectable({
providedIn: 'root'
......@@ -19,6 +20,12 @@ export class HelperService {
constructor(public http: HttpClient) {
}
// The translate loader needs to know where to load i18n files
// in Ionic's static asset pipeline.
static createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
static goToFeedbackPage(navCtrl: NavController) {
navCtrl.navigateForward('/feedback').then();
}
......
import {NgModule} from '@angular/core';
import {TranslateModule} from '@ngx-translate/core';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {HomePage} from 'src/app/home/home.page';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {IonicModule} from '@ionic/angular';
import {RouterModule} from '@angular/router';
import {HttpClient} from "@angular/common/http";
import {HelperService} from "src/app/helper.service";
@NgModule({
declarations: [
HomePage,
],
entryComponents: [],
imports: [
CommonModule,
FormsModule,
......@@ -20,7 +23,13 @@ import {RouterModule} from '@angular/router';
component: HomePage
}
]),
TranslateModule.forChild(),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: (HelperService.createTranslateLoader),
deps: [HttpClient]
}
})
],
exports: [
HomePage
......
......@@ -5,6 +5,9 @@
</div>
<div class="toolbar-right">
<ion-spinner *ngIf="HelperService.isLoading"></ion-spinner>
<button (click)="changeLanguage($event).then()">
<img src="{{'assets/imgs/' + translate.currentLang + '.svg'}}" width="40px" height="24px">
</button>
<button (click)="HelperService.goToFeedbackPage(navCtrl)">
<ion-icon name="help-circle"></ion-icon>
</button>
......@@ -27,7 +30,7 @@
<ion-row>
<ion-col>
<br>
<ion-button (click)="test()" [ngClass]="isProductionEnv">{{ 'TEST' | translate }}</ion-button>
<ion-button *ngIf="isProductionEnv" (click)="test()">{{ 'TEST' | translate }}</ion-button>
</ion-col>
</ion-row>
<ion-row *ngIf="HelperService.mostRecentSetup" padding-top>
......
.lastMainElement {
height: 50%;
height: 40%;
}
// celebration (balloons) background for the front page
//ion-content {
......
import {Component} from '@angular/core';
import {HelperService} from 'src/app/helper.service';
import {NavController, ToastController} from '@ionic/angular';
import {NavController, PopoverController, ToastController} from '@ionic/angular';
import {HttpClient} from '@angular/common/http';
import {TranslateService} from '@ngx-translate/core';
import {ExerciseService} from 'src/app/exercise.service';
import {CorpusService} from 'src/app/corpus.service';
import {ChangeLanguagePage} from "src/app/change-language/change-language.page";
@Component({
selector: 'app-home',
......@@ -12,22 +13,32 @@ import {CorpusService} from 'src/app/corpus.service';
styleUrls: ['home.page.scss'],
})
export class HomePage {
public isProductionEnv = ['localhost'].indexOf(window.location.hostname) > -1 ? '' : 'hide';
HelperService = HelperService;
public corpusUpdateCompletedString: string;
public isCorpusUpdateInProgress = false;
public isProductionEnv = ['localhost'].indexOf(window.location.hostname) > -1;
constructor(public navCtrl: NavController,
public http: HttpClient,
public exerciseService: ExerciseService,
public translate: TranslateService,
public corpusService: CorpusService,
public toastCtrl: ToastController) {
public toastCtrl: ToastController,
public popoverController: PopoverController) {
this.translate.get('CORPUS_UPDATE_COMPLETED').subscribe(value => this.corpusUpdateCompletedString = value);
// need to do this here because TranslateService is unavailable in the HelperService
this.translate.get('ERROR_GENERAL_ALERT').subscribe(value => HelperService.generalErrorAlertMessage = value);
}
async changeLanguage(ev: any = null) {
const popover = await this.popoverController.create({
component: ChangeLanguagePage,
event: ev,
translucent: true
});
return await popover.present();
}
goToAuthorPage() {
HelperService.isVocabularyCheck = false;
this.navCtrl.navigateForward('/author').then();
......
......@@ -48,7 +48,6 @@ export class PreviewPage {
}
this.processAnnisResponse(this.exerciseService.annisResponse);
this.initH5P();
this.updateFileUrl();
}
public initH5P() {
......@@ -81,6 +80,7 @@ export class PreviewPage {
});
}, 50);
}
this.updateFileUrl();
}
public processAnnisResponse(ar: AnnisResponse) {
......@@ -116,7 +116,6 @@ export class PreviewPage {
this.currentSolutions = [];
this.processSolutions(this.exerciseService.annisResponse.solutions);
this.initH5P();
this.updateFileUrl();
}
private updateFileUrl() {
......
......@@ -80,7 +80,7 @@
</ion-row>
<ion-row>
<ion-col>
<ion-button (click)="checkVocabulary()">{{ 'VOCABULARY_CHECK' | translate }}</ion-button>
<ion-button (click)="checkVocabulary().then()">{{ 'VOCABULARY_CHECK' | translate }}</ion-button>
</ion-col>
</ion-row>
</ion-grid>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment