-
Notifications
You must be signed in to change notification settings - Fork 2
/
relationview.ts
118 lines (95 loc) · 4.17 KB
/
relationview.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/// <reference path="_data.d.ts" />
import utils = require("../utils");
import dataset = require("./dataset");
import dataview = require("./dataview");
import _query = require("./query");
//#region Interfaces
export interface RelationView<T, TKey, TForeign, TForeignKey> extends dataview.DataView<TForeign, TForeignKey> {
propertyName: string;
parent: any;
localSet: dataset.DataSet<T, TKey>;
foreignSet: dataset.DataSet<TForeign, TForeignKey>;
localId: string;
localIdValue: any;
foreignId: string;
ensureRemote: boolean;
}
//#endregion
//#region Model
/** Create an observable relation to many entities */
export function create<T, TKey, TForeign, TForeignKey>(propertyName: string, localSet: dataset.DataSet<T, TKey>, parent: any, foreignSet: dataset.DataSet<TForeign, TForeignKey>, localId: string, foreignId: string, ensureRemote: boolean): RelationView<T, TKey, TForeign, TForeignKey> {
var self = {
propertyName: propertyName,
parent: parent,
localId: localId,
localSet: localSet,
localIdValue: ko.utils.unwrapObservable(parent[localId]),
foreignId: foreignId,
ensureRemote: ensureRemote
};
var result: any = foreignSet.createView(new _query.ODataQuery().where(self.foreignId, _query.operator.equal, self.parent[self.localId]));
self.parent[self.localId].subscribe(function (newId) {
if (self.localIdValue !== newId) {
var foreigns = foreignSet.filter(e => e[self.foreignId]() === self.localIdValue);
_.each(foreigns, foreign => foreign[self.foreignId](newId));
self.localIdValue = newId;
}
});
ko.utils.extend(result, self);
ko.utils.extend(result, relationViewFunctions);
return result;
}
var relationViewFunctions = {
/** Refresh foreign entities from the server */
refresh: function (): JQueryPromise<any> {
if (this.ensureRemote) {
var foreignSet = this.set,
localSet = this.localSet,
query = this.query,
self = this,
count;
return localSet.adapter
.getRelation(localSet.setName, self.propertyName, ko.utils.unwrapObservable(self.parent[self.localId]))
.then(function (data) {
if (data["odata.metadata"]) {
if (data["odata.count"])
count = data["odata.count"];
data = data.value;
}
else if (data.__count) {
count = data.__count;
data = data.results;
}
else if (!query) {
count = data.length;
}
return data;
})
.then(function (data) {
var existings = self.map(function (entity) { return foreignSet.getKey(entity); }),
news = _.map(data, function (entity) { return foreignSet.getKey(entity); }),
filter, args, hasToDelete, toDelete;
if (query) {
filter = query.toLocalFilter();
if (filter)
existings = _.filter(existings, filter);
hasToDelete = (query.pageSize() <= 0); //TODO: exec view function to check if item is in query
}
if (hasToDelete) {
args = news; args.unshift(existings);
toDelete = _.without.apply(_, args);
foreignSet.detachRange(toDelete);
}
return foreignSet.attachOrUpdateRange(data);
});
}
else
return dataview.dataViewFunctions.refresh.call(this);
},
/** Add entity to foreign entities and set it good value in foreign key, if buffer is false, entity will be instantly post on the server */
add: function (entity: any): JQueryPromise<any> {
entity[this.foreignId](ko.utils.unwrapObservable(this.parent[this.localId]));
return this.set.add(entity);
}
};
//#endregion