Refactor stores to use generic store (CC-61)
parent
421d15d19a
commit
8e46b6c6f1
|
@ -1,7 +1,6 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {AdminComponent} from './admin.component';
|
||||
import {SharedModule} from '../shared.module';
|
||||
import {AppUserStore} from '../services/stores/app-user.store';
|
||||
import {AppUserService} from '../services/app-user-service/app-user.service';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {RouterModule} from '@angular/router';
|
||||
|
@ -9,7 +8,7 @@ import {RouterModule} from '@angular/router';
|
|||
@NgModule({
|
||||
declarations: [AdminComponent],
|
||||
imports: [CommonModule, SharedModule, RouterModule.forChild([{path: '', component: AdminComponent}])],
|
||||
providers: [AppUserStore, AppUserService]
|
||||
providers: [AppUserService]
|
||||
})
|
||||
export class AdminModule {
|
||||
}
|
||||
|
|
|
@ -5,10 +5,7 @@ import {AppComponent} from './app.component';
|
|||
import {LoginService} from './services/app-user-service/login-service';
|
||||
import {appRouting, routingComponents, routingProviders} from './app.routing';
|
||||
import {SquadService} from './services/army-management/squad.service';
|
||||
import {SquadStore} from './services/stores/squad.store';
|
||||
import {DecorationStore} from './services/stores/decoration.store';
|
||||
import {DecorationService} from './services/army-management/decoration.service';
|
||||
import {RankStore} from './services/stores/rank.store';
|
||||
import {RankService} from './services/army-management/rank.service';
|
||||
import {AppConfig} from './app.config';
|
||||
import {LoginGuardAdmin, LoginGuardHL, LoginGuardSQL} from './login';
|
||||
|
@ -19,7 +16,6 @@ import {PromotionService} from './services/army-management/promotion.service';
|
|||
import {SharedModule} from './shared.module';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {UserService} from './services/army-management/user.service';
|
||||
import {UserStore} from './services/stores/user.store';
|
||||
import {CookieService} from 'ngx-cookie-service';
|
||||
import {SnackBarService} from './services/user-interface/snack-bar/snack-bar.service';
|
||||
import {HttpClientModule} from '@angular/common/http';
|
||||
|
@ -48,14 +44,10 @@ import {SettingsService} from './services/settings.service';
|
|||
LoginGuardHL,
|
||||
LoginGuardAdmin,
|
||||
UserService,
|
||||
UserStore,
|
||||
ArmyService,
|
||||
SquadService,
|
||||
SquadStore,
|
||||
DecorationService,
|
||||
DecorationStore,
|
||||
RankService,
|
||||
RankStore,
|
||||
AwardingService,
|
||||
PromotionService,
|
||||
AppConfig,
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {SharedModule} from '../shared.module';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {RankService} from '../services/army-management/rank.service';
|
||||
import {DecorationService} from '../services/army-management/decoration.service';
|
||||
|
||||
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
|
||||
import {manageRouterModule, manageRoutingComponents} from './manage.routing';
|
||||
import {InfiniteScrollModule} from 'ngx-infinite-scroll';
|
||||
import {DecorationStore} from '../services/stores/decoration.store';
|
||||
import {RankStore} from '../services/stores/rank.store';
|
||||
import {SquadStore} from '../services/stores/squad.store';
|
||||
import {SquadService} from '../services/army-management/squad.service';
|
||||
|
||||
export function createTranslateLoader(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './assets/i18n/manage/', '.json');
|
||||
|
@ -35,15 +28,6 @@ export function createTranslateLoader(http: HttpClient) {
|
|||
},
|
||||
isolate: true
|
||||
})
|
||||
],
|
||||
|
||||
providers: [
|
||||
RankStore,
|
||||
RankService,
|
||||
DecorationStore,
|
||||
DecorationService,
|
||||
SquadStore,
|
||||
SquadService
|
||||
]
|
||||
})
|
||||
export class ManageModule {
|
||||
|
|
|
@ -5,7 +5,7 @@ import {ActivatedRoute, Router} from '@angular/router';
|
|||
import {Observable} from 'rxjs/Observable';
|
||||
import {UserService} from '../../../services/army-management/user.service';
|
||||
import {User} from '../../../models/model-interfaces';
|
||||
import {ADD, LOAD} from '../../../services/stores/user.store';
|
||||
import {ADD, LOAD} from '../../../services/stores/generic-store';
|
||||
import {Fraction} from '../../../utils/fraction.enum';
|
||||
import {MatButtonToggleGroup} from '@angular/material';
|
||||
import {UIHelpers} from '../../../utils/global.helpers';
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {AppUser} from '../../models/model-interfaces';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {EDIT, LOAD, REMOVE} from '../stores/user.store';
|
||||
import {EDIT, LOAD, REMOVE, Store} from '../stores/generic-store';
|
||||
import {AppConfig} from '../../app.config';
|
||||
import {HttpClient} from '../http-client';
|
||||
import {AppUserStore} from '../stores/app-user.store';
|
||||
|
||||
@Injectable()
|
||||
export class AppUserService {
|
||||
|
||||
users$: Observable<AppUser[]>;
|
||||
|
||||
private appUserStore = new Store<AppUser>();
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private appUserStore: AppUserStore,
|
||||
private config: AppConfig) {
|
||||
this.users$ = appUserStore.items$;
|
||||
this.users$ = this.appUserStore.items$;
|
||||
}
|
||||
|
||||
getUsers() {
|
||||
|
@ -43,5 +43,4 @@ export class AppUserService {
|
|||
this.appUserStore.dispatch({type: REMOVE, data: user});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,22 +2,21 @@ import {Injectable} from '@angular/core';
|
|||
import {Decoration} from '../../models/model-interfaces';
|
||||
import {RequestMethod, RequestOptions, URLSearchParams} from '@angular/http';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {ADD, DecorationStore, EDIT, LOAD, REMOVE} from '../stores/decoration.store';
|
||||
import {ADD, EDIT, LOAD, REMOVE, Store} from '../stores/generic-store';
|
||||
import {AppConfig} from '../../app.config';
|
||||
import {HttpClient} from '../http-client';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class DecorationService {
|
||||
|
||||
decorations$: Observable<Decoration[]>;
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private decorationStore: DecorationStore,
|
||||
private config: AppConfig) {
|
||||
this.decorations$ = decorationStore.items$;
|
||||
}
|
||||
decorationStore = new Store<Decoration>();
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private config: AppConfig) {
|
||||
this.decorations$ = this.decorationStore.items$;
|
||||
}
|
||||
|
||||
findDecorations(query = '', fractionFilter?) {
|
||||
const searchParams = new URLSearchParams();
|
||||
|
@ -72,7 +71,6 @@ export class DecorationService {
|
|||
body = decoration;
|
||||
}
|
||||
|
||||
|
||||
const options = new RequestOptions({
|
||||
body: body,
|
||||
method: requestMethod,
|
||||
|
@ -86,7 +84,6 @@ export class DecorationService {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
deleteDecoration(decoration: Decoration) {
|
||||
return this.http.delete(this.config.apiDecorationPath + decoration._id)
|
||||
.do(res => {
|
||||
|
@ -94,4 +91,3 @@ export class DecorationService {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {Decoration, Rank} from '../../models/model-interfaces';
|
||||
import {Rank} from '../../models/model-interfaces';
|
||||
import {RequestMethod, RequestOptions, URLSearchParams} from '@angular/http';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {LOAD} from '../stores/decoration.store';
|
||||
import {ADD, EDIT, RankStore, REMOVE} from '../stores/rank.store';
|
||||
import {ADD, EDIT, LOAD, REMOVE, Store} from '../stores/generic-store';
|
||||
import {AppConfig} from '../../app.config';
|
||||
import {HttpClient} from '../http-client';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RankService {
|
||||
|
||||
ranks$: Observable<Rank[]>;
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private rankStore: RankStore,
|
||||
private config: AppConfig) {
|
||||
this.ranks$ = rankStore.items$;
|
||||
}
|
||||
rankStore = new Store<Rank>();
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private config: AppConfig) {
|
||||
this.ranks$ = this.rankStore.items$;
|
||||
}
|
||||
|
||||
findRanks(query = '', fractionFilter?) {
|
||||
const searchParams = new URLSearchParams();
|
||||
|
@ -90,55 +88,10 @@ export class RankService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* send PATCH request to update db entry
|
||||
*
|
||||
* @param rank - Rank object with data to update, must contain _id
|
||||
* @returns {Observable<T>}
|
||||
*/
|
||||
updateRank(rank: Rank) {
|
||||
const options = new RequestOptions({
|
||||
body: rank,
|
||||
method: RequestMethod.Patch
|
||||
});
|
||||
|
||||
return this.http.request(this.config.apiRankPath + rank._id, options)
|
||||
.map(res => res.json())
|
||||
.do(savedRank => {
|
||||
const action = {type: EDIT, data: savedRank};
|
||||
this.rankStore.dispatch(action);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* sends PATCH with multiform data to
|
||||
* update rank graphic with newly provided file
|
||||
*
|
||||
* @param rankID - id of rank to be updated
|
||||
* @param imageFile - new image file to upload
|
||||
*/
|
||||
updateRankGraphic(rankId: string, imageFile: File) {
|
||||
const formData: FormData = new FormData();
|
||||
formData.append('_id', rankId);
|
||||
formData.append('image', imageFile, imageFile.name);
|
||||
|
||||
// provide token as query value, because there is no actual body
|
||||
// and x-access-token is ignored in multipart request
|
||||
return this.http.patch(this.config.apiRankPath + rankId, formData)
|
||||
.map(res => res.json())
|
||||
.do(savedDecoration => {
|
||||
const action = {type: EDIT, data: savedDecoration};
|
||||
this.rankStore.dispatch(action);
|
||||
});
|
||||
}
|
||||
|
||||
deleteRank(rank: Rank) {
|
||||
return this.http.delete(this.config.apiRankPath + rank._id)
|
||||
.do(res => {
|
||||
this.rankStore.dispatch({type: REMOVE, data: rank});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ import {Injectable} from '@angular/core';
|
|||
import {Squad} from '../../models/model-interfaces';
|
||||
import {RequestMethod, RequestOptions, URLSearchParams} from '@angular/http';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
|
||||
import {ADD, EDIT, LOAD, REMOVE, SquadStore} from '../stores/squad.store';
|
||||
import {ADD, EDIT, LOAD, REMOVE, Store} from '../stores/generic-store';
|
||||
import {AppConfig} from '../../app.config';
|
||||
import {HttpClient} from '../http-client';
|
||||
|
||||
|
@ -12,10 +11,11 @@ export class SquadService {
|
|||
|
||||
squads$: Observable<Squad[]>;
|
||||
|
||||
squadStore = new Store<Squad>();
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private squadStore: SquadStore,
|
||||
private config: AppConfig) {
|
||||
this.squads$ = squadStore.items$;
|
||||
this.squads$ = this.squadStore.items$;
|
||||
}
|
||||
|
||||
findSquads(query = '', fractionFilter = '') {
|
||||
|
@ -33,13 +33,11 @@ export class SquadService {
|
|||
return this.squads$;
|
||||
}
|
||||
|
||||
|
||||
getSquad(id: number | string): Observable<Squad> {
|
||||
return this.http.get(this.config.apiSquadPath + id)
|
||||
.map(res => res.json());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For creating new data with POST or
|
||||
* update existing with patch PATCH
|
||||
|
@ -90,6 +88,4 @@ export class SquadService {
|
|||
this.squadStore.dispatch({type: REMOVE, data: squad});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Injectable} from '@angular/core';
|
|||
import {User} from '../../models/model-interfaces';
|
||||
import {URLSearchParams} from '@angular/http';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {ADD, EDIT, LOAD, REMOVE, UserStore} from '../stores/user.store';
|
||||
import {ADD, EDIT, LOAD, REMOVE, Store} from '../stores/generic-store';
|
||||
import {AppConfig} from '../../app.config';
|
||||
import {HttpClient} from '../http-client';
|
||||
|
||||
|
@ -11,12 +11,13 @@ export class UserService {
|
|||
|
||||
users$: Observable<User[]>;
|
||||
|
||||
userStore = new Store<User>();
|
||||
|
||||
totalCount = 0;
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private userStore: UserStore,
|
||||
private config: AppConfig) {
|
||||
this.users$ = userStore.items$;
|
||||
this.users$ = this.userStore.items$;
|
||||
}
|
||||
|
||||
findUsers(filter, limit?, offset?, action = LOAD) {
|
||||
|
@ -81,6 +82,4 @@ export class UserService {
|
|||
this.userStore.dispatch({type: REMOVE, data: user});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -14,5 +14,4 @@ export class ArmyService {
|
|||
return this.http.get(this.config.apiOverviewPath)
|
||||
.map(res => res.json());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ export class HttpClient {
|
|||
this.router.navigate(['/login']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
get(url, searchParams?) {
|
||||
|
@ -73,5 +72,4 @@ export class HttpClient {
|
|||
return this.patch(requestUrl, options.body);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,4 +42,3 @@ export class CampaignService {
|
|||
.map(res => res.json());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||
import {AppUser} from '../../models/model-interfaces';
|
||||
|
||||
export const LOAD = 'LOAD';
|
||||
export const ADD = 'ADD';
|
||||
export const EDIT = 'EDIT';
|
||||
export const REMOVE = 'REMOVE';
|
||||
|
||||
export class AppUserStore {
|
||||
|
||||
private appUsers: AppUser[] = [];
|
||||
|
||||
items$ = new BehaviorSubject<AppUser[]>([]);
|
||||
|
||||
dispatch(action) {
|
||||
this.appUsers = this._reduce(this.appUsers, action);
|
||||
this.items$.next(this.appUsers);
|
||||
}
|
||||
|
||||
_reduce(users: AppUser[], action) {
|
||||
switch (action.type) {
|
||||
case LOAD:
|
||||
return [...action.data];
|
||||
case ADD:
|
||||
return [...users, action.data];
|
||||
case EDIT:
|
||||
return users.map(user => {
|
||||
const editedUser = action.data;
|
||||
if (user._id !== editedUser._id) {
|
||||
return user;
|
||||
}
|
||||
return editedUser;
|
||||
});
|
||||
case REMOVE:
|
||||
return users.filter(user => user._id !== action.data._id);
|
||||
default:
|
||||
return users;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||
import {Decoration} from '../../models/model-interfaces';
|
||||
|
||||
export const LOAD = 'LOAD';
|
||||
export const ADD = 'ADD';
|
||||
export const EDIT = 'EDIT';
|
||||
export const REMOVE = 'REMOVE';
|
||||
|
||||
export class DecorationStore {
|
||||
|
||||
private decorations: Decoration[] = [];
|
||||
|
||||
items$ = new BehaviorSubject<Decoration[]>([]);
|
||||
|
||||
dispatch(action) {
|
||||
this.decorations = this._reduce(this.decorations, action);
|
||||
this.items$.next(this.decorations);
|
||||
}
|
||||
|
||||
_reduce(decorations: Decoration[], action) {
|
||||
switch (action.type) {
|
||||
case LOAD:
|
||||
return [...action.data];
|
||||
case ADD:
|
||||
return [...decorations, action.data];
|
||||
case EDIT:
|
||||
return decorations.map(decoration => {
|
||||
const editedDecoration = action.data;
|
||||
if (decoration._id !== editedDecoration._id) {
|
||||
return decoration;
|
||||
}
|
||||
return editedDecoration;
|
||||
});
|
||||
case REMOVE:
|
||||
return decorations.filter(decoration => decoration._id !== action.data._id);
|
||||
default:
|
||||
return decorations;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@ export const REMOVE = 'REMOVE';
|
|||
type Id = string | number;
|
||||
|
||||
interface Identifiable {
|
||||
id?: Id;
|
||||
_id?: Id;
|
||||
}
|
||||
|
||||
export class Store<T extends Identifiable> {
|
||||
|
@ -28,15 +28,15 @@ export class Store<T extends Identifiable> {
|
|||
case ADD:
|
||||
return [...items, action.data];
|
||||
case EDIT:
|
||||
return items.map(task => {
|
||||
const editedTask = action.data;
|
||||
if (task.id !== editedTask.id) {
|
||||
return task;
|
||||
return items.map(item => {
|
||||
const editedItem = action.data;
|
||||
if (item._id !== editedItem._id) {
|
||||
return item;
|
||||
}
|
||||
return editedTask;
|
||||
return editedItem;
|
||||
});
|
||||
case REMOVE:
|
||||
return items.filter(task => task.id !== action.data.id);
|
||||
return items.filter(item => item._id !== action.data._id);
|
||||
default:
|
||||
return items;
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||
import {Rank} from '../../models/model-interfaces';
|
||||
|
||||
export const LOAD = 'LOAD';
|
||||
export const ADD = 'ADD';
|
||||
export const EDIT = 'EDIT';
|
||||
export const REMOVE = 'REMOVE';
|
||||
|
||||
export class RankStore {
|
||||
|
||||
private ranks: Rank[] = [];
|
||||
|
||||
items$ = new BehaviorSubject<Rank[]>([]);
|
||||
|
||||
dispatch(action) {
|
||||
this.ranks = this._reduce(this.ranks, action);
|
||||
this.items$.next(this.ranks);
|
||||
}
|
||||
|
||||
_reduce(ranks: Rank[], action) {
|
||||
switch (action.type) {
|
||||
case LOAD:
|
||||
return [...action.data];
|
||||
case ADD:
|
||||
return [...ranks, action.data];
|
||||
case EDIT:
|
||||
return ranks.map(decoration => {
|
||||
const editedRank = action.data;
|
||||
if (decoration._id !== editedRank._id) {
|
||||
return decoration;
|
||||
}
|
||||
return editedRank;
|
||||
});
|
||||
case REMOVE:
|
||||
return ranks.filter(decoration => decoration._id !== action.data._id);
|
||||
default:
|
||||
return ranks;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||
import {Squad} from '../../models/model-interfaces';
|
||||
|
||||
export const LOAD = 'LOAD';
|
||||
export const ADD = 'ADD';
|
||||
export const EDIT = 'EDIT';
|
||||
export const REMOVE = 'REMOVE';
|
||||
|
||||
export class SquadStore {
|
||||
|
||||
private squads: Squad[] = [];
|
||||
|
||||
items$ = new BehaviorSubject<Squad[]>([]);
|
||||
|
||||
dispatch(action) {
|
||||
this.squads = this._reduce(this.squads, action);
|
||||
this.items$.next(this.squads);
|
||||
}
|
||||
|
||||
_reduce(squads: Squad[], action) {
|
||||
switch (action.type) {
|
||||
case LOAD:
|
||||
return [...action.data];
|
||||
case ADD:
|
||||
return [...squads, action.data];
|
||||
case EDIT:
|
||||
return squads.map(squad => {
|
||||
const editedSquad = action.data;
|
||||
if (squad._id !== editedSquad._id) {
|
||||
return squad;
|
||||
}
|
||||
return editedSquad;
|
||||
});
|
||||
case REMOVE:
|
||||
return squads.filter(squad => squad._id !== action.data._id);
|
||||
default:
|
||||
return squads;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||
import {User} from '../../models/model-interfaces';
|
||||
|
||||
export const LOAD = 'LOAD';
|
||||
export const ADD = 'ADD';
|
||||
export const EDIT = 'EDIT';
|
||||
export const REMOVE = 'REMOVE';
|
||||
|
||||
export class UserStore {
|
||||
|
||||
private users: User[] = [];
|
||||
|
||||
items$ = new BehaviorSubject<User[]>([]);
|
||||
|
||||
dispatch(action) {
|
||||
this.users = this._reduce(this.users, action);
|
||||
this.items$.next(this.users);
|
||||
}
|
||||
|
||||
_reduce(users: User[], action) {
|
||||
switch (action.type) {
|
||||
case LOAD:
|
||||
return [...action.data];
|
||||
case ADD:
|
||||
if (action.data instanceof Array) {
|
||||
return users.concat(action.data);
|
||||
}
|
||||
return [...users, action.data];
|
||||
case EDIT:
|
||||
return users.map(user => {
|
||||
const editedUser = action.data;
|
||||
if (user._id !== editedUser._id) {
|
||||
return user;
|
||||
}
|
||||
return editedUser;
|
||||
});
|
||||
case REMOVE:
|
||||
return users.filter(user => user._id !== action.data._id);
|
||||
default:
|
||||
return users;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue