aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/store/store.js
blob: da288a5dfbd4ec972903dbc7ac496981d776cfe1 (plain)
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
119
120
121
122
123
function Store() {
    this._views = [];
    this.reset();
}
_.extend(Store.prototype, {
    add: function (elem) {
        if (elem.id in this._pos_map) {
            return;
        }

        this._pos_map[elem.id] = this._list.length;
        this._list.push(elem);
        for (var i = 0; i < this._views.length; i++) {
            this._views[i].add(elem);
        }
    },
    update: function (elem) {
        if (!(elem.id in this._pos_map)) {
            return;
        }

        this._list[this._pos_map[elem.id]] = elem;
        for (var i = 0; i < this._views.length; i++) {
            this._views[i].update(elem);
        }
    },
    remove: function (elem_id) {
        if (!(elem.id in this._pos_map)) {
            return;
        }

        this._list.splice(this._pos_map[elem_id], 1);
        this._build_map();
        for (var i = 0; i < this._views.length; i++) {
            this._views[i].remove(elem_id);
        }
    },
    reset: function (elems) {
        this._list = elems || [];
        this._build_map();
        for (var i = 0; i < this._views.length; i++) {
            this._views[i].recalculate(this._list);
        }
    },
    _build_map: function () {
        this._pos_map = {};
        for (var i = 0; i < this._list.length; i++) {
            var elem = this._list[i];
            this._pos_map[elem.id] = i;
        }
    },
    get: function (elem_id) {
        return this._list[this._pos_map[elem_id]];
    },
    index: function(elem_id) {
        return this._pos_map[elem_id];
    }
});


function LiveStore(type) {
    Store.call(this);
    this.type = type;

    this._updates_before_fetch = undefined;
    this._fetchxhr = false;

    this.handle = this.handle.bind(this);
    AppDispatcher.register(this.handle);

    // Avoid double-fetch on startup.
    if (!(window.ws && window.ws.readyState === WebSocket.CONNECTING)) {
        this.fetch();
    }
}
_.extend(LiveStore.prototype, Store.prototype, {
    handle: function (event) {
        if (event.type === ActionTypes.CONNECTION_OPEN) {
            return this.fetch();
        }
        if (event.type === this.type) {
            if (event.cmd === StoreCmds.RESET) {
                this.fetch();
            } else if (this._updates_before_fetch) {
                console.log("defer update", event);
                this._updates_before_fetch.push(event);
            } else {
                this[event.cmd](event.data);
            }
        }
    },
    close: function () {
        AppDispatcher.unregister(this.handle);
    },
    fetch: function () {
        console.log("fetch " + this.type);
        if (this._fetchxhr) {
            this._fetchxhr.abort();
        }
        this._fetchxhr = $.getJSON("/" + this.type, this.handle_fetch.bind(this));
        this._updates_before_fetch = [];  // (JS: empty array is true)
    },
    handle_fetch: function (data) {
        this._fetchxhr = false;
        console.log(this.type + " fetched.", this._updates_before_fetch);
        this.reset(data.list);
        var updates = this._updates_before_fetch;
        this._updates_before_fetch = false;
        for (var i = 0; i < updates.length; i++) {
            this.handle(updates[i]);
        }
    },
});


function FlowStore() {
    return new LiveStore(ActionTypes.FLOW_STORE);
}


function EventLogStore() {
    return new LiveStore(ActionTypes.EVENT_STORE);
}