1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
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.
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.
18 // Indicate loading is in progress.
19 window.requestAnimationFrame(m.redraw)
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)
30 onupdate: function(vnode) {
31 vnode.state.loader = vnode.attrs.loader
33 onremove: function(vnode) {
34 window.clearInterval(vnode.state.timer)
35 window.removeEventListener('scroll', vnode.state.maybeLoadMore)
36 window.removeEventListener('resize', vnode.state.maybeLoadMore)
38 view: function(vnode) {
39 var loader = vnode.attrs.loader
40 return m('table.table.table-condensed', [
45 m('th', 'last modified'),
48 loader.items().map(function(item) {
51 // Guess workbench.{apihostport} is a
52 // Workbench... unless the host part of
53 // apihostport is an IPv4 or [IPv6]
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,
60 m('td.arvados-uuid', item.uuid),
61 m('td', item.name || '(unnamed)'),
62 m('td', m(LocalizedDateTime, {parse: item.modified_at})),
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',
75 disabled: loader.state == loader.LOADING,
80 }, loader.state == loader.LOADING ? '(loading)' : 'Load more')),
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({
103 loadFunc: function(filters) {
104 var tsquery = to_tsquery(q)
106 filters = filters.slice(0)
107 filters.push(['any', '@@', tsquery])
109 return vnode.state.sessionDB.request(session, 'arvados/v1/collections', {
111 filters: JSON.stringify(filters),
114 }).then(function(resp) {
115 resp.items.map(function(item) {
116 item.session = session
126 view: function(vnode) {
127 var sessions = vnode.state.sessionDB.loadAll()
129 onsubmit: function() {
130 vnode.state.searchActive(vnode.state.searchEntered())
131 vnode.state.forgetSavedHeight = true
137 currentState: vnode.state.searchActive,
138 forgetSavedHeight: vnode.state.forgetSavedHeight,
139 saveBodyHeight: true,
141 vnode.state.loader && [
145 m('input#search.form-control[placeholder=Search]', {
146 oninput: m.withAttr('value', vnode.state.searchEntered),
147 value: vnode.state.searchEntered(),
149 m('.input-group-btn', [
150 m('input.btn.btn-primary[type=submit][value="Search"]'),
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), ' ']
164 m('a[href="/sessions"]', 'Add/remove sites'),
167 m(CollectionsTable, {
168 loader: vnode.state.loader,