Commit a7a7f15f by Tuukka Kivilahti

Localization for moya

1 parent 22c3ff77
Showing with 523 additions and 59 deletions
...@@ -34,6 +34,8 @@ Jos tulee muita järkeviä kokonaisuuksia, joita voi käyttää muualla, jaa oma ...@@ -34,6 +34,8 @@ Jos tulee muita järkeviä kokonaisuuksia, joita voi käyttää muualla, jaa oma
## Hakemistohierarkia ## Hakemistohierarkia
Älykäs komponentti:
* app * app
* pages `tämän alla on käytännössä "älykkäät" komponentit (stateful), eli componentit jotka tietää mitä dataa haetaan ja mistä. Käytännössä route -targetit` * pages `tämän alla on käytännössä "älykkäät" komponentit (stateful), eli componentit jotka tietää mitä dataa haetaan ja mistä. Käytännössä route -targetit`
* user `Loppukäyttäjälle näkyvät jutut, ohjleman ns. main moduuli` * user `Loppukäyttäjälle näkyvät jutut, ohjleman ns. main moduuli`
...@@ -69,11 +71,14 @@ Jos tulee muita järkeviä kokonaisuuksia, joita voi käyttää muualla, jaa oma ...@@ -69,11 +71,14 @@ Jos tulee muita järkeviä kokonaisuuksia, joita voi käyttää muualla, jaa oma
* html * html
* ts * ts
* scss * scss
* components `servicet sekä componenttien geneeriset tyhmät osat tulevat tämän hakemiston alle ` * components `servicet sekä componenttien geneeriset tyhmät osat tulevat tämän hakemiston alle. Tänne voi myös pistää älykkäitä pieniä komponentteja `
* viplist * viplist
* list.component.ts * list.component.ts
* add.component.ts * add.component.ts
* modules `Kokonaiset, monessa paikassa olevt kokonaisuuksien tyhmät osat tulevat tänne. Sen verta isot että ne kannattaa tehdä moduuleiksi` * moya-locale
* moya-locale.service.ts
* moya-locale.model.ts `model -tiedosto joka on käytössä vaan moya-locale -servicessä`
* modules `Kokonaiset, monessa paikassa olevat kokonaisuuksien tyhmät osat tulevat tänne. Sen verta isot että ne kannattaa tehdä moduuleiksi`
* pizzatilaus * pizzatilaus
* anna-pizza.component.ts * anna-pizza.component.ts
* list-pizzat.component.ts,html,jne * list-pizzat.component.ts,html,jne
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
"@angular/platform-browser": "^5.2.9", "@angular/platform-browser": "^5.2.9",
"@angular/platform-browser-dynamic": "^5.2.9", "@angular/platform-browser-dynamic": "^5.2.9",
"@angular/router": "^5.2.9", "@angular/router": "^5.2.9",
"@ngx-translate/core": "^9.0.0",
"@ngx-translate/http-loader": "^2.0.0",
"bootstrap": "^4.0.0", "bootstrap": "^4.0.0",
"core-js": "^2.5.1", "core-js": "^2.5.1",
"ngx-bootstrap": "^2.0.2", "ngx-bootstrap": "^2.0.2",
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
<div id="contentarea"> <div id="contentarea">
<div id="topbar"> <div id="topbar">
<top-menu></top-menu> <top-menu></top-menu>
<moya-locale></moya-locale>
</div> </div>
<div id="content"> <div id="content">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
</div> </div>
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
} }
#contentarea { #contentarea {
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
...@@ -17,6 +16,9 @@ ...@@ -17,6 +16,9 @@
#topbar { #topbar {
margin-bottom: 30px; margin-bottom: 30px;
display: flex;
justify-content: space-between;
align-items: center;
} }
#content { #content {
......
import {Component, NgZone} from '@angular/core'; import {Component, NgZone} from '@angular/core';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {TranslateService} from "@ngx-translate/core";
import {DEFAULT_LOCALE, MoyaLocaleService} from "./components/moya-locale/moya-locale.service";
declare var window: any; declare var window: any;
...@@ -12,13 +14,17 @@ declare var window: any; ...@@ -12,13 +14,17 @@ declare var window: any;
}) })
export class AppComponent { export class AppComponent {
constructor(private router: Router, private zone: NgZone) { constructor(private router: Router, private zone: NgZone, private translate: TranslateService) {
window.angularRoute = (url => { window.angularRoute = (url => {
zone.run(() => { zone.run(() => {
router.navigateByUrl(url); router.navigateByUrl(url);
}); });
}); });
} }
} }
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {Injector, NgModule, ReflectiveInjector} from '@angular/core'; import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {AppComponent} from './app.component'; import {AppComponent} from './app.component';
...@@ -18,13 +18,15 @@ import {UserMenuComponent} from './menu/user-menu/user-menu.component'; ...@@ -18,13 +18,15 @@ import {UserMenuComponent} from './menu/user-menu/user-menu.component';
import {UserComponent} from './pages/user/user.component'; import {UserComponent} from './pages/user/user.component';
import {InfoComponent} from './pages/info/info.component'; import {InfoComponent} from './pages/info/info.component';
import {AdminComponent} from './pages/admin/admin.component'; import {AdminComponent} from './pages/admin/admin.component';
import {HttpClientModule, HttpHandler } from '@angular/common/http'; import {HttpClient, HttpClientModule} from '@angular/common/http';
import { HttpModule } from '@angular/http';
import {StaticInjector} from "@angular/core/src/di/injector";
import {CommonModule} from "@angular/common"; import {CommonModule} from "@angular/common";
import {CacheService} from "./shared/services/cache.service"; import {CacheService} from "./shared/services/cache.service";
import {MoyaRestModule} from "./moya-rest"; import {MoyaRestModule} from "./moya-rest";
import {SafePipe} from "./shared/pipes/safe.pipe"; import {SafePipe} from "./shared/pipes/safe.pipe";
import {TranslateLoader, TranslateModule} from "@ngx-translate/core";
import {TranslateHttpLoader} from "@ngx-translate/http-loader";
import {MoyaLocaleService} from "./components/moya-locale/moya-locale.service";
import { MoyaLocaleComponent } from './components/moya-locale/moya-locale.component';
const appRoutes: Routes = [ const appRoutes: Routes = [
{ {
...@@ -71,7 +73,8 @@ const appRoutes: Routes = [ ...@@ -71,7 +73,8 @@ const appRoutes: Routes = [
UserComponent, UserComponent,
InfoComponent, InfoComponent,
AdminComponent, AdminComponent,
SafePipe SafePipe,
MoyaLocaleComponent
], ],
imports: [ imports: [
...@@ -81,10 +84,18 @@ const appRoutes: Routes = [ ...@@ -81,10 +84,18 @@ const appRoutes: Routes = [
HttpClientModule, HttpClientModule,
AlertModule.forRoot(), AlertModule.forRoot(),
MoyaRestModule, MoyaRestModule,
//MoyaRestModule.forRoot(), RouterModule.forRoot(appRoutes),
RouterModule.forRoot(appRoutes) TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: function (http: HttpClient) {
return new TranslateHttpLoader(http, "assets/i18n/", ".json");
},
deps: [HttpClient]
}
})
], ],
providers: [CacheService], providers: [CacheService, MoyaLocaleService],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { export class AppModule {
......
<div id="flagBond">
<img src="assets/Flag_of_Finland.svg" [className]="(fiSelected)? 'disabledFlag':'flag' "height="20px" (click)="selectFinnish()" />
<img src="assets/Flag_of_Britain.svg" [className]="(enSelected)? 'disabledFlag':'flag'" height="20px" (click)="selectEnglish()" />
<img src="assets/Flag_of_Sweden.svg" [className]="(svSelected)? 'disabledFlag':'flag'" height="20px" (click)="selectSwedish()" />
</div>
.disabledFlag,
.flag {
border: 1px solid black;
margin-right: 3px;
cursor: pointer;
}
.disabledFlag {
opacity: 0.0;
cursor: auto;
border: none;
}
/* http://flexboxfroggy.com/ */
#flagBond {
display: flex;
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MoyaLocaleComponent } from './moya-locale.component';
describe('MoyaLocaleComponent', () => {
let component: MoyaLocaleComponent;
let fixture: ComponentFixture<MoyaLocaleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MoyaLocaleComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MoyaLocaleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import {DEFAULT_LOCALE, MoyaLocaleService} from "./moya-locale.service";
import {TranslateService} from "@ngx-translate/core";
const ENGLISH = "en";
const FINNISH = "fi";
const SWEDISH = "sv";
@Component({
selector: 'moya-locale',
templateUrl: './moya-locale.component.html',
styleUrls: ['./moya-locale.component.scss']
})
export class MoyaLocaleComponent implements OnInit {
fiSelected : boolean = true;
svSelected : boolean = true;
enSelected : boolean = true;
constructor(private localeService : MoyaLocaleService, private translate : TranslateService) {
// fallback language
translate.setDefaultLang(DEFAULT_LOCALE);
this.selectLocale(DEFAULT_LOCALE);
}
ngOnInit() {
this.localeService.getUserLocale().subscribe(locale => { this.selectLocale(locale)} );
}
selectLocale(locale : string, save :boolean = false):void {
if(![ENGLISH, FINNISH, SWEDISH].includes(locale)) {
return;
}
this.translate.use(locale);
this.fiSelected = this.svSelected = this.enSelected = false;
switch (locale) {
case FINNISH:
this.fiSelected = true;
break;
case ENGLISH:
this.enSelected = true;
break;
case SWEDISH:
this.svSelected = true;
break;
}
if(save) {
this.localeService.setUserLocale(locale).subscribe();
}
}
selectEnglish() {
this.selectLocale(ENGLISH, true);
}
selectFinnish() {
this.selectLocale(FINNISH, true);
}
selectSwedish() {
this.selectLocale(SWEDISH, true);
}
}
export class MoyaLocale {
public userLocale?: string;
public eventLocale?: string;
constructor() { }
}
import { TestBed, inject } from '@angular/core/testing';
import { MoyaLocaleService } from './moya-locale.service';
describe('MoyaLocaleService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [MoyaLocaleService]
});
});
it('should be created', inject([MoyaLocaleService], (service: MoyaLocaleService) => {
expect(service).toBeTruthy();
}));
});
import { Injectable } from '@angular/core';
import {MoyaRestService} from "../../shared/services/moya-rest.service";
import {Observable} from "rxjs/Observable";
import {MoyaLocale} from "./moya-locale.model";
export const DEFAULT_LOCALE = "fi";
const LOCALSTORAGE_NAME = "currently used locale code";
@Injectable()
export class MoyaLocaleService {
constructor(private moyaRest : MoyaRestService) { }
/**
* Order of Locale:
* 1. User's locale from database
* 2. User's locale from cookie
* 3. Event's locale from database
* 4. Default
*
* @return {Observable<string>} Return current locale as a string. No errors.
*/
public getUserLocale(): Observable<string> {
return this.moyaRest.get("/v3/locale/").catch(x => null ).map(untypedLocale => {
const locale = untypedLocale as MoyaLocale;
if (locale.userLocale) {
return locale.userLocale;
}
let cookieLocale = localStorage.getItem(LOCALSTORAGE_NAME);
if(cookieLocale) {
return cookieLocale;
}
if(locale.eventLocale) {
return locale.eventLocale;
}
return DEFAULT_LOCALE;
});
}
/**
* Store user's locale. This will store it to server. Or server is not available, into localstorage.
*
* There is no errors
* @param {string} locale
* @return {Promise<any>} This will return promise, but it will contain nothing.
*/
public setUserLocale(locale: string): Observable<any> {
let newLocale: MoyaLocale = new MoyaLocale();
newLocale.userLocale = locale;
// let's save locale to database, if it fails, we save it into localstorage. No errors to show for user.
return this.moyaRest.post("/v3/locale/", newLocale).first().catch(x => {
localStorage.setItem(LOCALSTORAGE_NAME, locale);
return "ok";
});
}
}
<p> <p>
user works! {{'test.user' | translate}} works!
</p> </p>
<div translate>test.user</div>
...@@ -12,4 +12,5 @@ export class UserComponent implements OnInit { ...@@ -12,4 +12,5 @@ export class UserComponent implements OnInit {
ngOnInit() { ngOnInit() {
} }
} }
...@@ -12,22 +12,22 @@ export class MoyaRestService { ...@@ -12,22 +12,22 @@ export class MoyaRestService {
constructor(private http: HttpClient) { } constructor(private http: HttpClient) { }
post(subUrl: string, body: any, pathParameters?: Map<string, string>): Observable<any> { post(subUrl: string, body: any, pathParameters?: Map<string, string>): Observable<Object> {
return this.http.post(this.genUrl(subUrl, pathParameters), body) return this.http.post(this.genUrl(subUrl, pathParameters), body)
.catch(this.handleException); .catch(this.handleException);
} }
put(subUrl: string, body: any, pathParameters?: Map<string, string>): Observable<any> { put(subUrl: string, body: any, pathParameters?: Map<string, string>): Observable<Object> {
return this.http.put(this.genUrl(subUrl, pathParameters), body) return this.http.put(this.genUrl(subUrl, pathParameters), body)
.catch(this.handleException); .catch(this.handleException);
} }
delete(subUrl: string, pathParameters?: Map<string, string>): Observable<any> { delete(subUrl: string, pathParameters?: Map<string, string>): Observable<Object> {
return this.http.delete(this.genUrl(subUrl, pathParameters)) return this.http.delete(this.genUrl(subUrl, pathParameters))
.catch(this.handleException); .catch(this.handleException);
} }
get(subUrl: string, pathParameters?: Map<string, string>): Observable<any> { get(subUrl: string, pathParameters?: Map<string, string>): Observable<Object> {
return this.http.get(this.genUrl(subUrl, pathParameters)) return this.http.get(this.genUrl(subUrl, pathParameters))
.catch(this.handleException); .catch(this.handleException);
} }
...@@ -53,25 +53,10 @@ export class MoyaRestService { ...@@ -53,25 +53,10 @@ export class MoyaRestService {
} }
/*
private handleResponse(res: HttpResponse<any>) {
console.log(res);
// basicly, 200 statuscodes means success
if(!(res.status >= 200 && res.status <= 299 )) {
console.log("statuscode not between 200 and 299", res.status);
// next stop: handlerException
throw res;
}
return res;
}*/
private handleException(error: HttpResponse<any> | any) { private handleException(error: HttpResponse<any> | any) {
console.log("error on jira rest connection", error); console.log("error on MOYA rest connection", error);
// TODO: add handlers to 403's and other "not logged in" or "invalid permissions" // TODO: add handlers to 403's and other "not logged in" or "invalid permissions"
// -statuscodes, and route them using some nice global parameter // -statuscodes, and route them using some nice global parameter
......
...@@ -21,7 +21,7 @@ export class UserService { ...@@ -21,7 +21,7 @@ export class UserService {
return this.cacheService.cacheObservable("moya:UserService", path, return this.cacheService.cacheObservable("moya:UserService", path,
this.moyaRest.get(path) this.moyaRest.get(path)
.do(v => {console.log("getting user outside of cache", path)}) .do(v => {console.log("getting user outside of cache", path)})
.map(res => (<User> res.body))); .map(res => (<User> res)));
} }
} }
...@@ -27,11 +27,11 @@ export class ViplistService { ...@@ -27,11 +27,11 @@ export class ViplistService {
if (!searchString) { if (!searchString) {
return this.moyaRestService.get("v3/vip/all") return this.moyaRestService.get("v3/vip/all")
.switchMap(res => Observable.forkJoin(...res.map(apiRow => this.hostPopulator(apiRow)))); .switchMap(res => Observable.forkJoin(...(res as Array<any>).map(apiRow => this.hostPopulator(apiRow))));
} }
return this.moyaRestService.get("v3/vip/search/" + searchString) return this.moyaRestService.get("v3/vip/search/" + searchString)
.switchMap(v => Observable.forkJoin(...v.map(x => this.hostPopulator(x)))); .switchMap(v => Observable.forkJoin(...(v as Array<any>).map(x => this.hostPopulator(x))));
} }
...@@ -46,7 +46,7 @@ export class ViplistService { ...@@ -46,7 +46,7 @@ export class ViplistService {
if (!vip.id) if (!vip.id)
throw new Error("TODO: errori, tyhmä vippi"); throw new Error("TODO: errori, tyhmä vippi");
let res: HttpResponse<any> = await this.moyaRestService.delete("v3/vip/" + vip.id) let res: any = await this.moyaRestService.delete("v3/vip/" + vip.id)
.first() .first()
.toPromise(); .toPromise();
...@@ -55,19 +55,19 @@ export class ViplistService { ...@@ -55,19 +55,19 @@ export class ViplistService {
public getWithId(id: number): Observable<Vip> { public getWithId(id: number): Observable<Vip> {
return this.moyaRestService.get("v3/vip/" + id) return this.moyaRestService.get("v3/vip/" + id).map(x => x as Vip);
} }
public create(vip: Vip): Observable<Vip> { public create(vip: Vip): Observable<Vip> {
return this.moyaRestService.post("v3/vip/create", vip) return this.moyaRestService.post("v3/vip/create", vip).map(x => x as Vip);
} }
private hostPopulator(rawVip : any): Observable<Vip> { private hostPopulator(rawVip : any): Observable<Vip> {
return this.userService.get(rawVip.hostId) return this.userService.get(rawVip.hostId)
.map((u: User) => {rawVip.host = u; return <Vip> rawVip }); .map((u: User) => {rawVip.host = u; return <Vip> rawVip }).map(x => x as Vip);
} }
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 60 30"
width="1200"
height="600"
id="svg3403"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="Flag_of_the_United_Kingdom.svg">
<metadata
id="metadata3422">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3420" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="837"
id="namedview3418"
showgrid="false"
inkscape:zoom="0.3375"
inkscape:cx="177.77778"
inkscape:cy="300"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg3403" />
<clipPath
id="t">
<path
d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"
id="path3406" />
</clipPath>
<path
id="path3408"
d="m 1.7728048e-6,2e-6 0,29.999996 59.9999962271952,0 0,-29.999996 z"
style="fill:#00247d"
inkscape:connector-curvature="0" />
<g
transform="matrix(0.99923007,0,0,0.99796116,-41.704693,34.67408)"
id="g3504">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 41.743796,-34.736135 -0.0052,3.399613 23.299453,11.656015 -23.29292,11.6456408 -0.0083,3.3390294 6.709976,0.0081 23.299108,-11.6411232 23.34047,11.6413252 6.695117,0.0039 -1.9e-4,-3.3197576 -23.325557,-11.6770916 23.324297,-11.658534 0.003,-3.404701 -6.671587,-0.0012 -23.36561,11.710902 -23.408517,-11.705182 z"
id="path3410"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccccc" />
<g
id="g3475"
transform="matrix(1.000467,0,0,1.0025461,-90.083492,-1.0167386)">
<path
id="path3473"
style="opacity:1;fill:#cf142b;fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 161.74139,-18.612942 4.47326,-0.01609 25.56234,12.8005343 -0.0419,2.1537942 -29.99365,-14.9382355 z m 25.50494,-15.029538 4.33491,0.0062 -29.84225,15.030397 -0.002,-2.252586 25.50972,-12.784027 z m -42.74835,8.567988 -12.73919,-6.383243 0,-2.184788 29.98658,15.024487 -4.41926,0.0058 -12.82813,-6.46226 z m 17.24195,6.456629 0,2.184787 -25.50624,12.7726879 -4.46056,0.00281 29.9668,-14.9602819 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccccccccccccc" />
</g>
</g>
<g
transform="matrix(0.99923007,0,0,0.99796116,-71.704693,6.7005857)"
id="g3457">
<g
id="g3500">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 96.779206,-6.714273 0,10.0204288 -25.019259,0 0,10.0204282 25.019259,0 0,10.020429 10.007704,0 0,-10.020429 25.01926,0 0,-10.0204282 -25.01926,0 0,-10.0204288 -10.007704,0 z"
id="path3414"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cf142b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 98.780746,-6.714273 0,12.0245146 -27.020799,0 0,6.0122564 27.020799,0 0,12.024515 6.004624,0 0,-12.024515 27.0208,0 0,-6.0122564 -27.0208,0 0,-12.0245146 -6.004624,0 z"
id="path3416"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1100">
<rect width="1800" height="1100" fill="#fff"/>
<rect width="1800" height="300" y="400" fill="#003580"/>
<rect width="300" height="1100" x="500" fill="#003580"/>
</svg>
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 16 10">
<rect width="16" height="10" fill="#006aa7"/>
<rect width="2" height="10" x="5" fill="#fecc00"/>
<rect width="16" height="2" y="4" fill="#fecc00"/>
</svg>
{
"test": {
"user": "User"
}
}
{
"test": {
"user": "Käyttäjä"
}
}
{
"test": {
"user": "Userna"
}
}
...@@ -44,6 +44,11 @@ import fi.codecrew.moya.utilities.SearchResult; ...@@ -44,6 +44,11 @@ import fi.codecrew.moya.utilities.SearchResult;
@Local @Local
public interface UserBeanLocal { public interface UserBeanLocal {
String getUsersLocale();
void setUsersLocale(String locale);
List<EventUser> getUsers(); List<EventUser> getUsers();
SearchResult<User> getUsers(SearchQuery search); SearchResult<User> getUsers(SearchQuery search);
...@@ -69,8 +74,7 @@ public interface UserBeanLocal { ...@@ -69,8 +74,7 @@ public interface UserBeanLocal {
/** /**
* Search EventUser entity by User entity ID * Search EventUser entity by User entity ID
* *
* @param userid * @param userid ID of the User entity to be searcher
* ID of the User entity to be searcher
* @return * @return
*/ */
EventUser findByUserId(Integer userid, boolean createEventuser); EventUser findByUserId(Integer userid, boolean createEventuser);
...@@ -94,13 +98,9 @@ public interface UserBeanLocal { ...@@ -94,13 +98,9 @@ public interface UserBeanLocal {
boolean userExistsByEmail(String email); boolean userExistsByEmail(String email);
/** /**
* * @param invitemail Target mail
* @param invitemail * @param url Url to send
* Target mail * @param membership target group membership, if null we generate new one
* @param url
* Url to send
* @param membership
* target group membership, if null we generate new one
* @return * @return
*/ */
boolean invite(String invitemail, String url, GroupMembership membership); boolean invite(String invitemail, String url, GroupMembership membership);
...@@ -189,6 +189,7 @@ public interface UserBeanLocal { ...@@ -189,6 +189,7 @@ public interface UserBeanLocal {
/** /**
* Check that user's password matches. * Check that user's password matches.
*
* @param eventUser * @param eventUser
* @param password * @param password
* @return true if matches, false if does not, null if user not found. * @return true if matches, false if does not, null if user not found.
...@@ -196,13 +197,13 @@ public interface UserBeanLocal { ...@@ -196,13 +197,13 @@ public interface UserBeanLocal {
Boolean checkPassword(EventUser eventUser, String password); Boolean checkPassword(EventUser eventUser, String password);
/** /**
*
* @return List of moya -surperusers * @return List of moya -surperusers
*/ */
List<User> findSuperusers(); List<User> findSuperusers();
/** /**
* There is a textcode type that looks up the code in EventUser object. Do the lookup. * There is a textcode type that looks up the code in EventUser object. Do the lookup.
*
* @param code * @param code
* @return EventUser with the matching code * @return EventUser with the matching code
*/ */
......
...@@ -442,6 +442,10 @@ public class BootstrapBean implements BootstrapBeanLocal { ...@@ -442,6 +442,10 @@ public class BootstrapBean implements BootstrapBeanLocal {
"ALTER TABLE account_events DROP COLUMN delivered_count;" "ALTER TABLE account_events DROP COLUMN delivered_count;"
}); });
dbUpdates.add(new String[] {
"ALTER TABLE users ADD COLUMN locale TEXT DEFAULT NULL;"
});
} }
public BootstrapBean() { public BootstrapBean() {
......
...@@ -180,6 +180,28 @@ public class UserBean implements UserBeanLocal { ...@@ -180,6 +180,28 @@ public class UserBean implements UserBeanLocal {
private OrgRoleFacade orgRoleFacade; private OrgRoleFacade orgRoleFacade;
@Override @Override
public String getUsersLocale() {
if (!permbean.getCurrentUser().isAnonymous()) {
return permbean.getCurrentUser().getUser().getLocale();
}
return null;
}
@Override
public void setUsersLocale(String locale) {
if(permbean.getCurrentUser().isAnonymous()) {
return;
}
// Attach user to database
User u = userFacade.reload(permbean.getCurrentUser().getUser());
u.setLocale(locale);
}
@Override
@RolesAllowed(UserPermission.S_VIEW_ALL) @RolesAllowed(UserPermission.S_VIEW_ALL)
public List<EventUser> getUsers() { public List<EventUser> getUsers() {
...@@ -351,7 +373,7 @@ public class UserBean implements UserBeanLocal { ...@@ -351,7 +373,7 @@ public class UserBean implements UserBeanLocal {
PrintedCard card = ctbean.checkPrintedCard(user); PrintedCard card = ctbean.checkPrintedCard(user);
if(card != null) if (card != null)
ctbean.cardImageUpdated(card.getId()); ctbean.cardImageUpdated(card.getId());
return userimage; return userimage;
...@@ -498,10 +520,10 @@ public class UserBean implements UserBeanLocal { ...@@ -498,10 +520,10 @@ public class UserBean implements UserBeanLocal {
logger.info("Initializing password sending: {}, hash: {}", user, hash); logger.info("Initializing password sending: {}, hash: {}", user, hash);
if (hash == null || hash.length() < 20 || user == null || user.getEmail() == null || user.getEmail().length() <= 5) { if (hash == null || hash.length() < 20 || user == null || user.getEmail() == null || user.getEmail().length() <= 5) {
logger.info("Not sending email with params {} {}", new Object[] { user, hash }); logger.info("Not sending email with params {} {}", new Object[]{user, hash});
return false; return false;
} }
String path = MessageFormat.format(url, new Object[] { user.getId().toString(), hash }); String path = MessageFormat.format(url, new Object[]{user.getId().toString(), hash});
LanEvent event = eventBean.getCurrentEvent(); LanEvent event = eventBean.getCurrentEvent();
MailMessage msg = new MailMessage(); MailMessage msg = new MailMessage();
...@@ -509,7 +531,7 @@ public class UserBean implements UserBeanLocal { ...@@ -509,7 +531,7 @@ public class UserBean implements UserBeanLocal {
msg.setSubject(I18n.get("passwordreset.mailSubject", event.getName())); msg.setSubject(I18n.get("passwordreset.mailSubject", event.getName()));
msg.setMessage(I18n.get("passwordreset.mailBody", path)); msg.setMessage(I18n.get("passwordreset.mailBody", path));
logger.info("sending mail! user {} hash {} path {}", new Object[] { user, hash, path }); logger.info("sending mail! user {} hash {} path {}", new Object[]{user, hash, path});
utilbean.sendMail(msg); utilbean.sendMail(msg);
user.setConfirmHash(hash); user.setConfirmHash(hash);
return true; return true;
...@@ -944,7 +966,7 @@ public class UserBean implements UserBeanLocal { ...@@ -944,7 +966,7 @@ public class UserBean implements UserBeanLocal {
@Override @Override
public boolean isUserInRole(EventUser user, Integer roleId) { public boolean isUserInRole(EventUser user, Integer roleId) {
Set<Role> roles = localFindUsersRoles(user); Set<Role> roles = localFindUsersRoles(user);
logger.info("CHecking user {} roleid {} from roles {}, roles size{}", new Object[] { user, roleId, roles, roles.size() }); logger.info("CHecking user {} roleid {} from roles {}, roles size{}", new Object[]{user, roleId, roles, roles.size()});
addRecursive(roles, eventBean.getCurrentEvent().getDefaultRole()); addRecursive(roles, eventBean.getCurrentEvent().getDefaultRole());
for (Role r : roles) { for (Role r : roles) {
...@@ -1023,7 +1045,7 @@ public class UserBean implements UserBeanLocal { ...@@ -1023,7 +1045,7 @@ public class UserBean implements UserBeanLocal {
dstUser.addAccountevent(dstacc); dstUser.addAccountevent(dstacc);
accountEventFacade.create(dstacc); accountEventFacade.create(dstacc);
logger.info("Transferred {} credits with price {} for user {} from {} to {}", logger.info("Transferred {} credits with price {} for user {} from {} to {}",
new Object[] { count, creditPrice, srcUser.getUser(), srcUser, dstUser }); new Object[]{count, creditPrice, srcUser.getUser(), srcUser, dstUser});
dstTotal = dstTotal.add(dstacc.getTotal()); dstTotal = dstTotal.add(dstacc.getTotal());
} }
...@@ -1090,15 +1112,13 @@ public class UserBean implements UserBeanLocal { ...@@ -1090,15 +1112,13 @@ public class UserBean implements UserBeanLocal {
public String findUsernameByEmailUsername(String filter) { public String findUsernameByEmailUsername(String filter) {
User user = findUserByEmailUsername(filter); User user = findUserByEmailUsername(filter);
if(user == null) if (user == null)
return null; return null;
return user.getLogin(); return user.getLogin();
} }
@Override @Override
public User findUserByEmailUsername(String filter) { public User findUserByEmailUsername(String filter) {
User user = userFacade.findByLogin(filter); User user = userFacade.findByLogin(filter);
......
...@@ -104,6 +104,9 @@ public class User extends GenericEntity implements IUser { ...@@ -104,6 +104,9 @@ public class User extends GenericEntity implements IUser {
@Column(name = "phone") @Column(name = "phone")
private String phone = ""; private String phone = "";
@Column(name = "locale")
private String locale = "";
@OneToOne(cascade = CascadeType.ALL) @OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "current_image_id", referencedColumnName = "id") @JoinColumn(name = "current_image_id", referencedColumnName = "id")
private UserImage currentImage; private UserImage currentImage;
...@@ -438,4 +441,11 @@ public class User extends GenericEntity implements IUser { ...@@ -438,4 +441,11 @@ public class User extends GenericEntity implements IUser {
setMetaStringValue("shirtSize", size); setMetaStringValue("shirtSize", size);
} }
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
} }
package fi.codecrew.moya.rest.v3;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.rest.v3.pojo.LocalePojoV3;
import io.swagger.annotations.Api;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@RequestScoped
@Path("/v3/locale")
@Api(value = "/v3/locale", description = "Locale operations")
@Produces({MediaType.APPLICATION_JSON + "; charset=UTF-8"})
@Consumes({MediaType.APPLICATION_JSON})
public class LocaleRestViewV3 {
@EJB
private UserBeanLocal userBean;
@EJB
private EventBeanLocal eventBean;
@GET
@Path("/")
public Response getCurrentLocale() {
return Response.ok(LocalePojoV3.create(userBean.getUsersLocale(), eventBean.getCurrentEvent().getOrganiser().getBundleCountry())).build();
}
@POST
@Path("/")
public Response setCurrentLocale(LocalePojoV3 locale) {
userBean.setUsersLocale(locale.userLocale);
return Response.ok().build();
}
}
package fi.codecrew.moya.rest.v3.pojo;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement()
public class LocalePojoV3 {
public String userLocale = null;
public String eventLocale = null;
public static LocalePojoV3 create(String userLocale, String eventLocale) {
LocalePojoV3 p = new LocalePojoV3();
p.userLocale = userLocale;
p.eventLocale = eventLocale;
return p;
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!