Skip to content

Commit

Permalink
Re-activates the history mode (#1078)
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielInTheWorld authored May 9, 2022
1 parent b7866b0 commit 5ceb330
Show file tree
Hide file tree
Showing 61 changed files with 1,437 additions and 328 deletions.
2 changes: 1 addition & 1 deletion client/src/app/domain/interfaces/constructable.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Fqid } from 'src/app/domain/definitions/key-types';
export interface Constructable<T = any> {
new (...args: any[]): T;
prototype: string;
prototype: T;
name?: string;
}

Expand Down
29 changes: 27 additions & 2 deletions client/src/app/gateways/actions/action.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,34 @@ import { HttpService } from '../http.service';
import { Action } from './action';
import { ActionRequest, isActionError, isActionResponse } from './action-utils';

type ActionFn = () => boolean;
const ACTION_URL = `/system/action/handle_request`;

let uniqueFnId = 0;

@Injectable({
providedIn: 'root'
})
export class ActionService {
private readonly ACTION_URL = `/system/action/handle_request`;
private readonly _beforeActionFnMap: { [index: number]: ActionFn } = {};

public constructor(private http: HttpService) {}

public addBeforeActionFn(fn: () => boolean): number {
this._beforeActionFnMap[++uniqueFnId] = fn;
return uniqueFnId;
}

public removeBeforeActionFn(index: number): void {
delete this._beforeActionFnMap[index];
}

public async sendRequests<T>(requests: ActionRequest[]): Promise<T[] | null> {
if (!this.isAllowed()) {
return null;
}
console.log(`send requests:`, requests);
const response = await this.http.post<T>(this.ACTION_URL, requests);
const response = await this.http.post<T>(ACTION_URL, requests);
if (isActionError(response)) {
throw response.message;
} else if (isActionResponse<T>(response)) {
Expand All @@ -33,6 +50,14 @@ export class ActionService {
return new Action<T>(r => this.sendRequests<T>(r) as any, ...requests);
}

private isAllowed(): boolean {
const functions = Object.values(this._beforeActionFnMap);
if (!functions.length) {
return true;
}
return functions.some(fn => !fn());
}

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////// The following methods will be removed ///////////////////////
/////////////////////////////////////////////////////////////////////////////////////
Expand Down
14 changes: 11 additions & 3 deletions client/src/app/gateways/http-stream/http-stream.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const lostConnectionToFn = (endpoint: EndpointConfiguration) => {

type HttpParamsGetter = () => HttpParams | { [param: string]: string | string[] } | null;
type HttpBodyGetter = () => any;

type CreateEndpointFn = { endpointIndex: string; customUrlFn: (baseEndpointUrl: string) => string };

interface RequestOptions {
bodyFn?: HttpBodyGetter;
paramsFn?: HttpParamsGetter;
Expand All @@ -32,7 +35,7 @@ export class HttpStreamService {
) {}

public create<T>(
endpointConfiguration: string | EndpointConfiguration,
endpointConfiguration: string | CreateEndpointFn | EndpointConfiguration,
{
onError = (_, description) =>
this.onError(this.getEndpointConfiguration(endpointConfiguration), description),
Expand Down Expand Up @@ -98,11 +101,16 @@ export class HttpStreamService {
return true;
}

private getEndpointConfiguration(endpoint: string | EndpointConfiguration): EndpointConfiguration {
private getEndpointConfiguration(
endpoint: string | CreateEndpointFn | EndpointConfiguration
): EndpointConfiguration {
if (typeof endpoint === `string`) {
return this.endpointService.getEndpoint(endpoint);
} else {
} else if (endpoint instanceof EndpointConfiguration) {
return endpoint;
} else {
const configuration = this.endpointService.getEndpoint(endpoint.endpointIndex);
return { ...configuration, url: endpoint.customUrlFn(configuration.url) };
}
}
}
146 changes: 73 additions & 73 deletions client/src/app/gateways/notify.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,60 @@ export class NotifyService {
});
}

private async connect(meetingId: number): Promise<void> {
/**
* Returns a general observalbe of all notify messages.
*/
public getObservable(): Observable<NotifyResponse<any>> {
return this.notifySubject.asObservable();
}

/**
* Returns an observable which gets updates for a specific topic.
* @param name The name of a topic to subscribe to.
*/
public getMessageObservable<T>(name: string): Observable<NotifyResponse<T>> {
if (!this.messageSubjects[name]) {
this.messageSubjects[name] = new Subject<NotifyResponse<any>>();
}
return this.messageSubjects[name].asObservable() as Observable<NotifyResponse<T>>;
}

/**
* Sents a notify message to all users (so all clients that are online).
* @param name The name of the notify message
* @param content The payload to send
*/
public async sendToAllUsers<T>(name: string, content: T): Promise<void> {
await this.send({ name, message: content, toAll: true });
}

/**
* Sends a notify message to all open clients with the given users logged in.
* @param name The name of the enotify message
* @param content The payload to send.
* @param users Multiple user ids.
*/
public async sendToUsers<T>(name: string, content: T, ...users: number[]): Promise<void> {
if (users.length < 1) {
throw new Error(`You have to provide at least one user`);
}
await this.send({ name, message: content, users });
}

/**
* Sends a notify message to all given channels.
* @param name The name of th enotify message
* @param content The payload to send.
* @param channels Multiple channels to send this message to.
*/
public async sendToChannels<T>(name: string, content: T, ...channels: string[]): Promise<void> {
if (channels.length < 1) {
throw new Error(`You have to provide at least one channel`);
}
await this.send({ name, message: content, channels });
}

public async connect(meetingId: number): Promise<void> {
if (!meetingId) {
throw new Error(`Cannot connect to ICC, no meeting ID was provided`);
}
Expand All @@ -168,7 +221,7 @@ export class NotifyService {
this.connectionClosingFn = closeFn;
}

private disconnect(): void {
public disconnect(): void {
if (this.connectionClosingFn) {
try {
this.connectionClosingFn();
Expand All @@ -193,81 +246,28 @@ export class NotifyService {
}
}

/**
* Sents a notify message to all users (so all clients that are online).
* @param name The name of the notify message
* @param content The payload to send
*/
public async sendToAllUsers<T>(name: string, content: T): Promise<void> {
await this.send({ name, message: content, toAll: true });
}

/**
* Sends a notify message to all open clients with the given users logged in.
* @param name The name of the enotify message
* @param content The payload to send.
* @param users Multiple user ids.
*/
public async sendToUsers<T>(name: string, content: T, ...users: number[]): Promise<void> {
if (users.length < 1) {
throw new Error(`You have to provide at least one user`);
}
await this.send({ name, message: content, users });
}

/**
* Sends a notify message to all given channels.
* @param name The name of th enotify message
* @param content The payload to send.
* @param channels Multiple channels to send this message to.
*/
public async sendToChannels<T>(name: string, content: T, ...channels: string[]): Promise<void> {
if (channels.length < 1) {
throw new Error(`You have to provide at least one channel`);
}
await this.send({ name, message: content, channels });
}

/**
* General send function for notify messages.
*/
private async send<T>({ name, message, toAll, users, channels }: NotifySendOptions<T>): Promise<void> {
// if (!this.channelId) {
// throw new Error(`No channel id!`);
// }
// const notify: NotifyRequest<T> = {
// name,
// message,
// channel_id: this.channelId,
// to_meeting: this.activeMeetingIdService.meetingId!
// };
// if (toAll === true) {
// notify.to_all = true;
// }
// if (users) {
// notify.to_users = users;
// }
// if (channels) {
// notify.to_channels = channels;
// }
// await this.httpService.post<unknown>(PUBLISH_PATH, notify);
}

/**
* Returns a general observalbe of all notify messages.
*/
public getObservable(): Observable<NotifyResponse<any>> {
return this.notifySubject.asObservable();
}

/**
* Returns an observable which gets updates for a specific topic.
* @param name The name of a topic to subscribe to.
*/
public getMessageObservable<T>(name: string): Observable<NotifyResponse<T>> {
if (!this.messageSubjects[name]) {
this.messageSubjects[name] = new Subject<NotifyResponse<any>>();
if (!this.channelId) {
throw new Error(`No channel id!`);
}
return this.messageSubjects[name].asObservable() as Observable<NotifyResponse<T>>;
const notify: NotifyRequest<T> = {
name,
message,
channel_id: this.channelId,
to_meeting: this.activeMeetingIdService.meetingId!
};
if (toAll === true) {
notify.to_all = true;
}
if (users) {
notify.to_users = users;
}
if (channels) {
notify.to_channels = channels;
}
await this.httpService.post<unknown>(PUBLISH_PATH, notify);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { HistoryPresenterService } from './history-presenter.service';

describe('HistoryPresenterService', () => {
let service: HistoryPresenterService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(HistoryPresenterService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
92 changes: 92 additions & 0 deletions client/src/app/gateways/presenter/history-presenter.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Injectable } from '@angular/core';
import { Collection, Fqid, Id } from 'src/app/domain/definitions/key-types';
import { HttpService } from 'src/app/gateways/http.service';
import { UserRepositoryService } from 'src/app/gateways/repositories/users';
import { collectionFromFqid } from 'src/app/infrastructure/utils/transform-functions';

interface InformationObject {
[fqid: string]: string[];
}

export class Position {
public position: number;
public timestamp: number;
public information: InformationObject;
public user_id: Id;
public fqid: Fqid;

public constructor(input?: Partial<Position>) {
if (input) {
Object.assign(this, input);
}
}
}

export class HistoryPosition extends Position {
public user: string;

public get date(): Date {
return new Date(this.timestamp * 1000);
}

private get _collection(): Collection {
return collectionFromFqid(this.fqid);
}

public constructor(input?: Partial<HistoryPosition>) {
super(input);
if (input) {
Object.assign(this, input);
}
}

/**
* Converts the date (this.now) to a time and date string.
*
* @param locale locale indicator, i.e 'de-DE'
* @returns a human readable kind of time and date representation
*/
public getLocaleString(locale: string): string {
return this.date.toLocaleString(locale);
}

public getPositionDescriptions(): string[] {
const information = this.information[this.fqid];
return information.map(entry => entry.replace(`Object`, this._collection));
}
}

interface HistoryPresenterResponse {
[fqid: string]: Position[];
}

const HISTORY_ENDPOINT = `/system/autoupdate/history_information`;

const getUniqueItems = (positions: Position[]) => {
const positionMap: { [positionNumber: number]: Position } = {};
for (const position of positions) {
positionMap[position.position] = position;
}
return Object.values(positionMap);
};

@Injectable({
providedIn: 'root'
})
export class HistoryPresenterService {
public constructor(private http: HttpService, private userRepo: UserRepositoryService) {}

public async call(fqid: Fqid): Promise<HistoryPosition[]> {
const response = await this.http.post<HistoryPresenterResponse>(HISTORY_ENDPOINT, undefined, { fqid });
return Object.values(response)
.flatMap(positions => getUniqueItems(positions))
.sort((positionA, positionB) => positionB.timestamp - positionA.timestamp)
.map(position => {
return new HistoryPosition({
...position,
fqid,
user: this.userRepo.getViewModel(position.user_id)?.getFullName()
});
});
}
}
3 changes: 2 additions & 1 deletion client/src/app/gateways/presenter/presenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export enum Presenter {
GET_USER_RELATED_MODELS = `get_user_related_models`,
GET_USER_SCOPE = `get_user_scope`,
GET_FORWARDING_MEETINGS = `get_forwarding_meetings`,
SEARCH_USERS_BY_NAME_OR_EMAIL = `search_users_by_name_or_email`
SEARCH_USERS_BY_NAME_OR_EMAIL = `search_users_by_name_or_email`,
GET_HISTORY_INFORMATION = `get_history_information`
}
1 change: 1 addition & 0 deletions client/src/app/infrastructure/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './functions';
export * from './nullable-partial';
export * from './functionable';
export * from './lang-to-locale';
Loading

0 comments on commit 5ceb330

Please sign in to comment.