12194: Fix accidentally mutated argument.
[arvados.git] / apps / workbench / app / assets / javascripts / components / collections.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 window.CollectionsTable = {
6     maybeLoadMore: function(dom) {
7         var loader = this.loader
8         if (loader.state != loader.READY)
9             // Can't start getting more items anyway: no point in
10             // checking anything else.
11             return
12         var contentRect = dom.getBoundingClientRect()
13         var scroller = window // TODO: use dom's nearest ancestor with scrollbars
14         if (contentRect.bottom < 2 * scroller.innerHeight) {
15             // We have less than 1 page worth of content available
16             // below the visible area. Load more.
17             loader.loadMore()
18             // Indicate loading is in progress.
19             window.requestAnimationFrame(m.redraw)
20         }
21     },
22     oncreate: function(vnode) {
23         vnode.state.maybeLoadMore = vnode.state.maybeLoadMore.bind(vnode.state, vnode.dom)
24         window.addEventListener('scroll', vnode.state.maybeLoadMore)
25         window.addEventListener('resize', vnode.state.maybeLoadMore)
26         vnode.state.timer = window.setInterval(vnode.state.maybeLoadMore, 200)
27         vnode.state.loader = vnode.attrs.loader
28         vnode.state.onupdate(vnode)
29     },
30     onupdate: function(vnode) {
31         vnode.state.loader = vnode.attrs.loader
32     },
33     onremove: function(vnode) {
34         window.clearInterval(vnode.state.timer)
35         window.removeEventListener('scroll', vnode.state.maybeLoadMore)
36         window.removeEventListener('resize', vnode.state.maybeLoadMore)
37     },
38     view: function(vnode) {
39         var loader = vnode.attrs.loader
40         return m('table.table.table-condensed', [
41             m('thead', m('tr', [
42                 m('th'),
43                 m('th', 'uuid'),
44                 m('th', 'name'),
45                 m('th', 'last modified'),
46             ])),
47             m('tbody', [
48                 loader.items().map(function(item) {
49                     return m('tr', [
50                         m('td', [
51                             // Guess workbench.{apihostport} is a
52                             // Workbench... unless the host part of
53                             // apihostport is an IPv4 or [IPv6]
54                             // address.
55                             item.session.baseURL.match('://(\\[|\\d+\\.\\d+\\.\\d+\\.\\d+[:/])') ? null :
56                                 m('a.btn.btn-xs.btn-default', {
57                                     href: item.session.baseURL.replace('://', '://workbench.')+'collections/'+item.uuid,
58                                 }, 'Show'),
59                         ]),
60                         m('td.arvados-uuid', item.uuid),
61                         m('td', item.name || '(unnamed)'),
62                         m('td', m(LocalizedDateTime, {parse: item.modified_at})),
63                     ])
64                 }),
65             ]),
66             loader.state == loader.DONE ? null : m('tfoot', m('tr', [
67                 m('th[colspan=4]', m('button.btn.btn-xs', {
68                     className: loader.state == loader.LOADING ? 'btn-default' : 'btn-primary',
69                     style: {
70                         display: 'block',
71                         width: '12em',
72                         marginLeft: 'auto',
73                         marginRight: 'auto',
74                     },
75                     disabled: loader.state == loader.LOADING,
76                     onclick: function() {
77                         loader.loadMore()
78                         return false
79                     },
80                 }, loader.state == loader.LOADING ? '(loading)' : 'Load more')),
81             ])),
82         ])
83     },
84 }
85
86 window.CollectionsSearch = {
87     oninit: function(vnode) {
88         vnode.state.sessionDB = new SessionDB()
89         vnode.state.searchEntered = m.stream()
90         vnode.state.searchActive = m.stream()
91         // When searchActive changes (e.g., when restoring state
92         // after navigation), update the text field too.
93         vnode.state.searchActive.map(vnode.state.searchEntered)
94         // When searchActive changes, create a new loader that filters
95         // with the given search term.
96         vnode.state.searchActive.map(function(q) {
97             var sessions = vnode.state.sessionDB.loadActive()
98             vnode.state.loader = new MergingLoader({
99                 children: Object.keys(sessions).map(function(key) {
100                     var session = sessions[key]
101                     return new MultipageLoader({
102                         sessionKey: key,
103                         loadFunc: function(filters) {
104                             var tsquery = to_tsquery(q)
105                             if (tsquery) {
106                                 filters = filters.slice(0)
107                                 filters.push(['any', '@@', tsquery])
108                             }
109                             return vnode.state.sessionDB.request(session, 'arvados/v1/collections', {
110                                 data: {
111                                     filters: JSON.stringify(filters),
112                                     count: 'none',
113                                 },
114                             }).then(function(resp) {
115                                 resp.items.map(function(item) {
116                                     item.session = session
117                                 })
118                                 return resp
119                             })
120                         },
121                     })
122                 })
123             })
124         })
125     },
126     view: function(vnode) {
127         var sessions = vnode.state.sessionDB.loadAll()
128         return m('form', {
129             onsubmit: function() {
130                 vnode.state.searchActive(vnode.state.searchEntered())
131                 vnode.state.forgetSavedHeight = true
132                 return false
133             },
134         }, [
135             m(SaveUIState, {
136                 defaultState: '',
137                 currentState: vnode.state.searchActive,
138                 forgetSavedHeight: vnode.state.forgetSavedHeight,
139                 saveBodyHeight: true,
140             }),
141             vnode.state.loader && [
142                 m('.row', [
143                     m('.col-md-6', [
144                         m('.input-group', [
145                             m('input#search.form-control[placeholder=Search]', {
146                                 oninput: m.withAttr('value', vnode.state.searchEntered),
147                                 value: vnode.state.searchEntered(),
148                             }),
149                             m('.input-group-btn', [
150                                 m('input.btn.btn-primary[type=submit][value="Search"]'),
151                             ]),
152                         ]),
153                     ]),
154                     m('.col-md-6', [
155                         'Searching sites: ',
156                         vnode.state.loader.children.length == 0
157                             ? m('span.label.label-xs.label-danger', 'none')
158                             : vnode.state.loader.children.map(function(child) {
159                                 return [m('span.label.label-xs', {
160                                     className: child.state == child.LOADING ? 'label-warning' : 'label-success',
161                                 }, child.sessionKey), ' ']
162                             }),
163                         ' ',
164                         m('a[href="/sessions"]', 'Add/remove sites'),
165                     ]),
166                 ]),
167                 m(CollectionsTable, {
168                     loader: vnode.state.loader,
169                 }),
170             ],
171         ])
172     },
173 }