MainContext.ts
106 lines
| 3.9 KiB
| video/mp2t
|
TypeScriptLexer
cin
|
r107 | import Memory = require("dojo/store/Memory"); | ||
import Observable = require("dojo/store/Observable"); | ||||
import { Appointment, Member } from "./Appointment"; | ||||
import { Contact } from "./Contact"; | ||||
import { Uuid } from "@implab/core-amd/Uuid"; | ||||
import { Observable as RxjsObservable } from "rxjs"; | ||||
import { QueryResultUpdate } from "@implab/djx/tsx"; | ||||
type AppointmentRecord = Omit<Appointment, "getMembers"> & {id: string}; | ||||
type ContactRecord = Contact; | ||||
type MemberRecord = Member & { appointmentId: string; }; | ||||
export interface ObservableResults<T> { | ||||
/** | ||||
* Allows observation of results | ||||
*/ | ||||
observe(listener: (object: T, previousIndex: number, newIndex: number) => void, includeUpdates?: boolean): { | ||||
remove(): void; | ||||
}; | ||||
} | ||||
export function isObservable<T>(v: PromiseLike<ArrayLike<T>> | ArrayLike<T>): v is ArrayLike<T> & ObservableResults<T> { | ||||
return v && (typeof (v as any).observe === "function"); | ||||
} | ||||
export function observe<T>(results: T[], includeObjectUpdates?: boolean): RxjsObservable<QueryResultUpdate<T>>; | ||||
export function observe<T>(results: PromiseLike<T[]>, includeObjectUpdates?: boolean): PromiseLike<RxjsObservable<QueryResultUpdate<T>>>; | ||||
export function observe(results: any, includeObjectUpdates = true) { | ||||
// results может быть асинхронным, т.е. до завершения | ||||
// получения результатов store может быть обновлен. В любом | ||||
// случае, если между подключением хотя бы одного наблюдателя | ||||
// была выполнена команда обновления, results считается устаревшим | ||||
// и не может быть использован для отслеживания обновлений. | ||||
// Конкретно с dojo/store/Observable тут вообще возникает проблема: | ||||
// 1. Синхронные store типа Memory будут давать ошибку на методах | ||||
// обновления (add,put,remove) | ||||
// 2. Асинхронные store типа JsonRest будут выдавать предупреждения | ||||
// о необработанной ошибке в Promise при обращении к методам | ||||
// обновления (add,put,remove) | ||||
const _subscribe = (items: any[]) => new RxjsObservable<QueryResultUpdate<any>>(subscriber => { | ||||
items | ||||
.forEach((value, newIndex) => subscriber.next({ item: value, newIndex, prevIndex: -1})); | ||||
try { | ||||
if (isObservable(results)) { | ||||
const h = results.observe( | ||||
(value, prevIndex, newIndex) => subscriber.next({ | ||||
item: value, | ||||
prevIndex, | ||||
newIndex | ||||
}), | ||||
includeObjectUpdates | ||||
); | ||||
return () => { h.remove(); }; | ||||
} | ||||
} catch (err) { | ||||
subscriber.error(err); | ||||
} | ||||
}); | ||||
return isPromise(results) ? | ||||
results.then(_subscribe) : | ||||
_subscribe(results || []); | ||||
} | ||||
export class MainContext { | ||||
private _appointments = new Observable(new Memory<AppointmentRecord>()); | ||||
private _contacts = new Observable(new Memory<ContactRecord>()); | ||||
private _members = new Observable(new Memory<MemberRecord>()); | ||||
createAppointment(title: string, startAt: Date, duration: number, members: Member[]) { | ||||
const id = Uuid(); | ||||
this._appointments.add({ | ||||
id: Uuid(), | ||||
startAt, | ||||
duration, | ||||
title | ||||
}); | ||||
members.forEach(member => | ||||
this._members.add({ | ||||
appointmentId: id, | ||||
...member | ||||
}, {id: Uuid()}) | ||||
); | ||||
} | ||||
queryAppointments(dateFrom: Date, dateTo: Date) { | ||||
this._appointments.query().map() | ||||
} | ||||
private _mapAppointment = ({startAt, title, duration, id}: AppointmentRecord) => ({ | ||||
}) | ||||
} | ||||