blob: 631a9c5310192e448b623762bf20b283ceabe717 [file] [log] [blame]
Jiri Simsa653f9892015-03-24 23:03:42 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Ali Ghassemi5b408882015-01-16 14:58:00 -08005var mercury = require('mercury');
Alex Fandriantobd6e6f62015-01-22 10:38:37 -08006var uuid = require('uuid');
Ali Ghassemi5b408882015-01-16 14:58:00 -08007
8var GridView = require('./grid-view/index');
9var TreeView = require('./tree-view/index');
10var VisualizeView = require('./visualize-view/index');
11
12var namespaceService = require('../../../services/namespace/service');
13
14var log = require('../../../lib/log')('components:browse:items');
15
16module.exports = create;
17module.exports.render = render;
18module.exports.load = load;
19module.exports.trySetViewType = trySetViewType;
20
21var VALID_VIEW_TYPES = ['grid', 'tree', 'visualize'];
22
23/*
24 * Items view.
25 * Renders one of: Grid, Tree or Visualize views depending on the state
26 */
27function create() {
28
Wm Leler38540a82015-01-20 17:03:36 -080029 var treeComponent = new TreeView();
30
Ali Ghassemi5b408882015-01-16 14:58:00 -080031 var state = mercury.varhash({
32
Wm Leler38540a82015-01-20 17:03:36 -080033 tree: treeComponent.state,
34
Ali Ghassemi5b408882015-01-16 14:58:00 -080035 /*
36 * List of namespace items to display
37 * @see services/namespace/item
38 * @type {Array<namespaceitem>}
39 */
40 items: mercury.array([]),
41
42 /*
43 * Specifies the current view type of the items.
44 * One of: grid, tree, visualize
45 */
Ali Ghassemi27f1cf12015-02-04 13:49:56 -080046 viewType: mercury.value('tree'),
Ali Ghassemi5b408882015-01-16 14:58:00 -080047
48 /*
49 * uuid for the current browse-namespace request.
50 * Needed to handle out-of-order return of async calls.
51 * @type {String}
52 */
53 currentRequestId: mercury.value('')
54 });
55
Wm Leler38540a82015-01-20 17:03:36 -080056 var events = mercury.input([
57 'tree'
58 ]);
59
60 events.tree = treeComponent.events;
61
Ali Ghassemi5b408882015-01-16 14:58:00 -080062 return {
Wm Leler38540a82015-01-20 17:03:36 -080063 state: state,
64 events: events
Ali Ghassemi5b408882015-01-16 14:58:00 -080065 };
66}
67
68function trySetViewType(state, viewType) {
69 var isValid = VALID_VIEW_TYPES.indexOf(viewType) >= 0;
70 if (!isValid) {
71 return false;
72 }
73
74 state.viewType.set(viewType);
75 return true;
76}
77
78/*
79 * Does the initialization and loading of the data necessary to display the
80 * namespace items.
81 * Called and used by the parent browse view to initialize the view on
82 * request.
83 * Returns a promise that will be resolved when loading is finished. Promise
84 * is used by the parent browse view to display a loading progressbar.
85 */
86function load(state, namespace, globQuery) {
87
88 // TODO(aghassemi)
89 // -Rename the concept to "init", not every component may have it.
90 // does not return anything, we can have showLoadingIndicator(bool) be an
91 // functionality that can be requested of the browse view.
92 // -Move items to "GridView"
93 // -Have a common component between tree and vis to share the childrens map
94
Wm Leler38540a82015-01-20 17:03:36 -080095 if (state.viewType() === 'tree') {
Ali Ghassemi8f35ebb2015-02-05 10:55:36 -080096 TreeView.expand(state.tree, namespace);
Ali Ghassemicf34bf02015-04-21 17:14:04 -070097 return namespaceService.getNamespaceItem(namespace)
98 .then(function(item) {
99 state.tree.put('rootItem', item);
100 })
101 .catch(function(err) {
102 state.tree.put('rootItem', null);
103 return Promise.reject(err);
104 });
Wm Leler38540a82015-01-20 17:03:36 -0800105 }
106
Ali Ghassemi5b408882015-01-16 14:58:00 -0800107 if (state.viewType() !== 'grid') {
108 return Promise.resolve();
109 }
110
111 // Search the namespace and update the browseState's items.
Alex Fandriantobd6e6f62015-01-22 10:38:37 -0800112 var requestId = uuid.v4();
Ali Ghassemi5b408882015-01-16 14:58:00 -0800113 state.currentRequestId.set(requestId);
114 state.put('items', mercury.array([]));
115
116 return new Promise(function(resolve, reject) {
117 namespaceService.search(namespace, globQuery).
118 then(function globResultsReceived(items) {
119 if (!isCurrentRequest()) {
120 resolve();
121 return;
122 }
123 state.put('items', items);
Alex Fandrianto92157292015-01-30 10:51:01 -0800124 items.events.once('end', loadingFinished);
Ali Ghassemi65ee3262015-02-23 11:36:59 -0800125 items.events.on('globError', loadingFinished);
Ali Ghassemi5b408882015-01-16 14:58:00 -0800126 }).catch(function(err) {
127 log.error(err);
128 reject();
129 });
130
131 function loadingFinished() {
132 if (!isCurrentRequest()) {
133 return;
134 }
135 resolve();
136 }
137 });
138
139 // Whether we are still the current request. This is used to ignore out of
140 // order return of async calls where user has moved on to another item
141 // by the time previous requests result comes back.
142 function isCurrentRequest() {
143 return state.currentRequestId() === requestId;
144 }
145}
146
Wm Leler38540a82015-01-20 17:03:36 -0800147function render(state, events, browseState, browseEvents, navEvents) {
Ali Ghassemi5b408882015-01-16 14:58:00 -0800148 switch (state.viewType) {
149 case 'grid':
150 return GridView.render(state, browseState, browseEvents, navEvents);
151 case 'tree':
Wm Leler38540a82015-01-20 17:03:36 -0800152 return TreeView.render(state.tree, events.tree,
Ali Ghassemicf34bf02015-04-21 17:14:04 -0700153 browseState, browseEvents);
Ali Ghassemi5b408882015-01-16 14:58:00 -0800154 case 'visualize':
155 return VisualizeView.render(state, browseState, browseEvents, navEvents);
156 default:
157 log.error('Unsupported viewType: ' + state.viewType);
158 }
Ali Ghassemicf34bf02015-04-21 17:14:04 -0700159}