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

108 lines
3.7 KiB
TypeScript

import { Injectable } from '@angular/core';
import { environment } from 'environments/environment';
import { BaseModel } from 'app/shared/models/base/base-model';
import { History } from 'app/shared/models/core/history';
import { CollectionStringMapperService } from './collection-string-mapper.service';
import { DataStoreService, DataStoreUpdateManagerService } from './data-store.service';
import { HttpService } from './http.service';
import { OpenSlidesStatusService } from './openslides-status.service';
import { OpenSlidesService } from './openslides.service';
import { WebsocketService } from './websocket.service';
interface HistoryData {
[collection: string]: BaseModel[];
}
/**
* 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: CollectionStringMapperService,
private DS: DataStoreService,
private OSStatus: OpenSlidesStatusService,
private OpenSlides: OpenSlidesService,
private DSUpdateManager: DataStoreUpdateManagerService
) {}
/**
* 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> {
const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS);
await this.stopTime(history);
const historyData: HistoryData = await this.getHistoryData(history);
const allModels = [];
Object.keys(historyData).forEach(collection => {
const targetClass = this.modelMapperService.getModelConstructor(collection);
historyData[collection].forEach(model => {
allModels.push(new targetClass(model));
});
});
await this.DS.set(allModels, 0);
this.DSUpdateManager.commit(updateSlot, 1, true);
}
/**
* Leaves the history mode. Just restart OpenSlides:
* The active user is checked, a new WS connection established and
* all missed auto updates are requested.
*/
public async resumeTime(): Promise<void> {
this.OSStatus.leaveHistoryMode();
await this.DS.set();
await this.OpenSlides.reboot();
}
/**
* 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 queryParams = { timestamp: Math.ceil(history.timestamp) };
return await this.httpService.get<HistoryData>(
`${environment.urlPrefix}/core/history/data/`,
null,
queryParams
);
}
/**
* Clears the DataStore and stops the WebSocket connection
*/
private async stopTime(history: History): Promise<void> {
await this.webSocketService.close();
await this.DS.set(); // Same as clear, but not persistent.
this.OSStatus.enterHistoryMode(history);
}
}