OpenSlides/client/src/app/core/services/time-travel.service.ts

120 lines
4.1 KiB
TypeScript
Raw Normal View History

import { Injectable } from '@angular/core';
import { environment } from 'environments/environment';
import { CollectionStringModelMapperService } from './collectionStringModelMapper.service';
import { History } from 'app/shared/models/core/history';
import { DataStoreService } from './data-store.service';
import { WebsocketService } from './websocket.service';
import { BaseModel } from 'app/shared/models/base/base-model';
import { OpenSlidesStatusService } from './openslides-status.service';
import { OpenSlidesService } from './openslides.service';
import { HttpService } from './http.service';
/**
* Interface for full history data objects.
* The are not too different from the history-objects,
* but contain full-data and a timestamp in contrast to a date
*/
interface HistoryData {
element_id: string;
full_data: BaseModel;
information: string;
timestamp: number;
user_id: number;
}
/**
* Service to enable browsing OpenSlides in a previous version.
*
* This should stop auto updates, save the current ChangeID and overwrite the DataStore with old Values
* from the servers History.
*
* Restoring is nor possible yet. Simply reload
*/
@Injectable({
providedIn: 'root'
})
export class TimeTravelService {
/**
* Constructs the time travel service
*
* @param httpService To fetch the history data
* @param webSocketService to disable websocket connection
* @param modelMapperService to cast history objects into models
* @param DS to overwrite the dataStore
* @param OSStatus Sets the history status
* @param OpenSlides For restarting OpenSlide when exiting the history mode
*/
public constructor(
private httpService: HttpService,
private webSocketService: WebsocketService,
private modelMapperService: CollectionStringModelMapperService,
private DS: DataStoreService,
private OSStatus: OpenSlidesStatusService,
private OpenSlides: OpenSlidesService
) { }
/**
* Main entry point to set OpenSlides to another history point.
*
* @param history the desired point in the history of OpenSlides
*/
public async loadHistoryPoint(history: History): Promise<void> {
await this.stopTime();
const fullDataHistory: HistoryData[] = await this.getHistoryData(history);
for (const historyObject of fullDataHistory) {
let collectionString: string;
let id: string;
[collectionString, id] = historyObject.element_id.split(':')
if (historyObject.full_data) {
const targetClass = this.modelMapperService.getModelConstructor(collectionString);
await this.DS.add([new targetClass(historyObject.full_data)])
} else {
await this.DS.remove(collectionString, [+id]);
}
}
}
/**
* Leaves the history mode. Just restart OpenSlides:
* The active user is chacked, a new WS connection established and
* all missed autoupdates are requested.
*/
public async resumeTime(): Promise<void> {
await this.DS.set();
await this.OpenSlides.reboot();
this.OSStatus.leaveHistroyMode();
}
/**
* Read the history on a given time
*
* @param date the Date object
* @returns the full history on the given date
*/
private async getHistoryData(history: History): Promise<HistoryData[]> {
const historyUrl = '/core/history/'
const queryParams = { timestamp: Math.ceil(+history.unixtime) };
return this.httpService.get<HistoryData[]>(environment.urlPrefix + historyUrl, null, queryParams);
}
/**
* Clears the DataStore and stops the WebSocket connection
*/
private async stopTime(): Promise<void> {
this.webSocketService.close();
await this.cleanDataStore();
this.OSStatus.enterHistoryMode();
}
/**
* Clean the DataStore to inject old Data.
* Remove everything "but" the history.
*/
private async cleanDataStore(): Promise<void> {
const historyArchive = this.DS.getAll(History);
await this.DS.set(historyArchive);
}
}