Typescriptify stores

This commit is contained in:
Jannis Mattheis 2018-04-19 21:10:01 +02:00 committed by Jannis Mattheis
parent 915f40638b
commit c404dee96d
11 changed files with 142 additions and 126 deletions

View File

@ -1,33 +0,0 @@
import {EventEmitter} from 'events';
import dispatcher from './dispatcher';
class AppStore extends EventEmitter {
constructor() {
super();
this.apps = [];
}
get() {
return this.apps;
}
getById(id) {
return this.apps.find((app) => app.id === id);
}
getName(id) {
const app = this.getById(id);
return id === -1 ? 'All Messages' : app !== undefined ? app.name : 'unknown';
}
handle(data) {
if (data.type === 'UPDATE_APPS') {
this.apps = data.payload;
this.emit('change');
}
}
}
const store = new AppStore();
dispatcher.register(store.handle.bind(store));
export default store;

38
ui/src/stores/AppStore.ts Normal file
View File

@ -0,0 +1,38 @@
import {EventEmitter} from 'events';
import dispatcher, {IEvent} from './dispatcher';
class AppStore extends EventEmitter {
private apps: IApplication[] = [];
public get(): IApplication[] {
return this.apps;
}
public getById(id: number): IApplication {
const app = this.getByIdOrUndefined(id);
if (!app) {
throw new Error('app is required to exist')
}
return app;
}
public getName(id: number): string {
const app = this.getByIdOrUndefined(id);
return id === -1 ? 'All Messages' : app !== undefined ? app.name : 'unknown';
}
public handle(data: IEvent): void {
if (data.type === 'UPDATE_APPS') {
this.apps = data.payload;
this.emit('change');
}
}
private getByIdOrUndefined(id: number): IApplication | undefined {
return this.apps.find((a) => a.id === id);
}
}
const store = new AppStore();
dispatcher.register(store.handle.bind(store));
export default store;

View File

@ -1,34 +0,0 @@
import {EventEmitter} from 'events';
import dispatcher from './dispatcher';
class ClientStore extends EventEmitter {
constructor() {
super();
this.clients = [];
}
get() {
return this.clients;
}
getById(id) {
return this.clients.find((client) => client.id === id);
}
getIdByToken(token) {
const client = this.clients.find((client) => client.token === token);
return client !== undefined ? client.id : '';
}
handle(data) {
if (data.type === 'UPDATE_CLIENTS') {
this.clients = data.payload;
this.emit('change');
}
}
}
const store = new ClientStore();
dispatcher.register(store.handle.bind(store));
export default store;

View File

@ -0,0 +1,35 @@
import {EventEmitter} from 'events';
import {default as dispatcher, IEvent} from './dispatcher';
class ClientStore extends EventEmitter {
private clients: IClient[] = [];
public get(): IClient[] {
return this.clients;
}
public getById(id: number): IClient {
const client = this.clients.find((c) => c.id === id);
if (!client) {
throw new Error('client is required to exist')
}
return client;
}
public getIdByToken(token: string): number {
const client = this.clients.find((c) => c.token === token);
return client !== undefined ? client.id : -1;
}
public handle(data: IEvent): void {
if (data.type === 'UPDATE_CLIENTS') {
this.clients = data.payload;
this.emit('change');
}
}
}
const store = new ClientStore();
dispatcher.register(store.handle.bind(store));
export default store;

View File

@ -1,40 +1,31 @@
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import dispatcher from './dispatcher'; import dispatcher, {IEvent} from './dispatcher';
class GlobalStore extends EventEmitter { class GlobalStore extends EventEmitter {
constructor() { private currentUser: IUser | null = null;
super(); private isAuthenticating = true;
this.currentUser = null;
this.isAuthenticating = true;
}
authenticating() { public authenticating(): boolean {
return this.isAuthenticating; return this.isAuthenticating;
} }
get() { public get(): IUser {
return this.currentUser || {name: 'unknown', admin: false}; return this.currentUser || {name: 'unknown', admin: false, id: -1};
} }
isAdmin() { public isAdmin(): boolean {
return this.get().admin; return this.get().admin;
} }
getName() { public getName(): string {
return this.get().name; return this.get().name;
} }
isLoggedIn() { public isLoggedIn(): boolean {
return this.currentUser != null; return this.currentUser != null;
} }
set(user) { public handle(data: IEvent): void {
this.isAuthenticating = false;
this.currentUser = user;
this.emit('change');
}
handle(data) {
if (data.type === 'NO_AUTHENTICATION') { if (data.type === 'NO_AUTHENTICATION') {
this.set(null); this.set(null);
} else if (data.type === 'AUTHENTICATED') { } else if (data.type === 'AUTHENTICATED') {
@ -44,6 +35,12 @@ class GlobalStore extends EventEmitter {
this.emit('change'); this.emit('change');
} }
} }
private set(user: IUser | null): void {
this.isAuthenticating = false;
this.currentUser = user;
this.emit('change');
}
} }
const store = new GlobalStore(); const store = new GlobalStore();

View File

@ -1,23 +1,25 @@
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import dispatcher from './dispatcher';
import AppStore from './AppStore';
import * as MessageAction from '../actions/MessageAction'; import * as MessageAction from '../actions/MessageAction';
import AppStore from './AppStore';
import dispatcher, {IEvent} from './dispatcher';
class MessageStore extends EventEmitter { class MessageStore extends EventEmitter {
private appToMessages: { [appId: number]: IAppMessages } = {};
private reset: false | number = false;
private resetOnAll: false | number = false;
private loading = false;
constructor() { constructor() {
super(); super();
this.appToMessages = {};
this.reset = false;
this.resetOnAll = false;
this.loading = false;
AppStore.on('change', () => { AppStore.on('change', () => {
this.updateApps(); this.updateApps();
this.emit('change'); this.emit('change');
}); });
} }
shouldReset(appId) { public shouldReset(appId: number): false | number {
let reset = appId === -1 ? this.resetOnAll : this.reset; const reset = appId === -1 ? this.resetOnAll : this.reset;
if (reset !== false) { if (reset !== false) {
this.reset = false; this.reset = false;
this.resetOnAll = false; this.resetOnAll = false;
@ -25,7 +27,7 @@ class MessageStore extends EventEmitter {
return reset; return reset;
} }
loadNext(id) { public loadNext(id: number): void {
if (this.loading || !this.get(id).hasMore) { if (this.loading || !this.get(id).hasMore) {
return; return;
} }
@ -33,7 +35,7 @@ class MessageStore extends EventEmitter {
MessageAction.fetchMessagesApp(id, this.get(id).nextSince).catch(() => this.loading = false); MessageAction.fetchMessagesApp(id, this.get(id).nextSince).catch(() => this.loading = false);
} }
get(id) { public get(id: number): IAppMessages {
if (this.exists(id)) { if (this.exists(id)) {
return this.appToMessages[id]; return this.appToMessages[id];
} else { } else {
@ -41,11 +43,11 @@ class MessageStore extends EventEmitter {
} }
} }
exists(id) { public exists(id: number): boolean {
return this.appToMessages[id] !== undefined; return this.appToMessages[id] !== undefined;
} }
handle(data) { public handle(data: IEvent): void {
const {payload} = data; const {payload} = data;
if (data.type === 'UPDATE_MESSAGES') { if (data.type === 'UPDATE_MESSAGES') {
if (this.exists(payload.id)) { if (this.exists(payload.id)) {
@ -83,7 +85,7 @@ class MessageStore extends EventEmitter {
} }
} }
removeFromList(messages, messageToDelete) { private removeFromList(messages: IAppMessages, messageToDelete: IMessage): false | number {
if (messages) { if (messages) {
const index = messages.messages.findIndex((message) => message.id === messageToDelete.id); const index = messages.messages.findIndex((message) => message.id === messageToDelete.id);
if (index !== -1) { if (index !== -1) {
@ -94,11 +96,11 @@ class MessageStore extends EventEmitter {
return false; return false;
} }
updateApps = () => { private updateApps = (): void => {
const appToUrl = {}; const appToUrl: { [appId: number]: string } = {};
AppStore.get().forEach((app) => appToUrl[app.id] = app.image); AppStore.get().forEach((app) => appToUrl[app.id] = app.image);
Object.keys(this.appToMessages).forEach((key) => { Object.keys(this.appToMessages).forEach((key) => {
const appMessages = this.appToMessages[key]; const appMessages: IAppMessages = this.appToMessages[key];
appMessages.messages.forEach((message) => message.image = appToUrl[message.appid]); appMessages.messages.forEach((message) => message.image = appToUrl[message.appid]);
}); });
}; };

View File

@ -1,5 +1,5 @@
import dispatcher from './dispatcher';
import Notify from 'notifyjs'; import Notify from 'notifyjs';
import dispatcher, {IEvent} from './dispatcher';
export function requestPermission() { export function requestPermission() {
if (Notify.needsPermission && Notify.isSupported()) { if (Notify.needsPermission && Notify.isSupported()) {
@ -8,22 +8,24 @@ export function requestPermission() {
} }
} }
function closeAndFocus(event) { function closeAndFocus(event: Event) {
if (window.parent) { if (window.parent) {
window.parent.focus(); window.parent.focus();
} }
window.focus(); window.focus();
window.location.href = '/'; window.location.href = '/';
event.target.close(); const target = event.target as Notification;
target.close();
} }
function closeAfterTimeout(event) { function closeAfterTimeout(event: Event) {
setTimeout(() => { setTimeout(() => {
event.target.close(); const target = event.target as Notification;
target.close();
}, 5000); }, 5000);
} }
dispatcher.register((data) => { dispatcher.register((data: IEvent): void => {
if (data.type === 'ONE_MESSAGE') { if (data.type === 'ONE_MESSAGE') {
const msg = data.payload; const msg = data.payload;

View File

@ -1,18 +1,21 @@
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import dispatcher from './dispatcher'; import dispatcher, {IEvent} from './dispatcher';
class SnackBarStore extends EventEmitter { class SnackBarStore extends EventEmitter {
messages = []; public messages: string[] = [];
next() { public next(): string {
return this.messages.shift(); if (!this.hasNext()) {
throw new Error("no such element")
}
return this.messages.shift() as string;
} }
hasNext() { public hasNext(): boolean {
return this.messages.length !== 0; return this.messages.length !== 0;
} }
handle(data) { public handle(data: IEvent): void {
if (data.type === 'SNACK') { if (data.type === 'SNACK') {
this.messages.push(data.payload); this.messages.push(data.payload);
this.emit('change'); this.emit('change');

View File

@ -1,21 +1,22 @@
import {EventEmitter} from 'events'; import {EventEmitter} from 'events';
import dispatcher from './dispatcher'; import dispatcher, {IEvent} from './dispatcher';
class UserStore extends EventEmitter { class UserStore extends EventEmitter {
constructor() { private users: IUser[] = [];
super();
this.users = [];
}
get() { public get(): IUser[] {
return this.users; return this.users;
} }
getById(id) { public getById(id: number): IUser {
return this.users.find((app) => app.id === id); const user = this.users.find((u) => u.id === id);
if (!user) {
throw new Error('user must exist');
}
return user;
} }
handle(data) { public handle(data: IEvent): void {
if (data.type === 'UPDATE_USERS') { if (data.type === 'UPDATE_USERS') {
this.users = data.payload; this.users = data.payload;
this.emit('change'); this.emit('change');

View File

@ -1,3 +0,0 @@
import {Dispatcher} from 'flux';
export default new Dispatcher();

View File

@ -0,0 +1,8 @@
import {Dispatcher} from 'flux';
export interface IEvent {
type: string
payload?: any
}
export default new Dispatcher<IEvent>();