@@ -23,6 +23,7 @@ export default { | |||
'src/css/index.css': 'dist/css/index.css', | |||
'node_modules/bootstrap/dist/css/bootstrap.min.css': 'dist/css/bootstrap.min.css', | |||
'node_modules/bootstrap/dist/js/bootstrap.min.js': 'dist/js/bootstrap.min.js', | |||
'node_modules/jquery/dist/jquery.min.js': 'dist/js/jquery.min.js', | |||
verbose: true | |||
}), | |||
buble({jsx: 'h'}), | |||
@@ -2,6 +2,7 @@ | |||
<head> | |||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |||
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css" /> | |||
<script language="javascript" src="/js/jquery.min.js"></script> | |||
<script language="javascript" src="/js/bootstrap.min.js"></script> | |||
</head> | |||
<body> | |||
@@ -1,37 +1,24 @@ | |||
import { h, Component } from 'preact'; | |||
import WBTabs from 'wb-tabs'; | |||
import WBTable from 'wb-table'; | |||
import WBPagination from 'wb-pagination'; | |||
class WBApp extends Component { | |||
render() { | |||
return ( | |||
<div> | |||
<h1>WBApp</h1> | |||
<table class="table table-striped table-hover"> | |||
<thead class="thead-light"> | |||
<tr> | |||
<th>Name</th> | |||
<th>Description</th> | |||
<th>Size</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td>Name</td> | |||
<td>Description</td> | |||
<td>0 bytes</td> | |||
</tr> | |||
<tr> | |||
<td>Name</td> | |||
<td>Description</td> | |||
<td>0 bytes</td> | |||
</tr> | |||
<tr> | |||
<td>Name</td> | |||
<td>Description</td> | |||
<td>0 bytes</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
<WBPagination numPages={ 100 } activePage={ 0 } | |||
onPageChanged={ idx => alert(idx) } /> | |||
<WBTable | |||
columns={ [ 'Name', 'Description', 'Size' ] } | |||
rows={ [ | |||
[ 'Name', 'Description', '0 bytes'], | |||
[ 'Name', 'Description', '0 bytes'], | |||
[ 'Name', 'Description', '0 bytes'], | |||
[ 'Name', 'Description', '0 bytes'], | |||
[ 'Name', 'Description', '0 bytes'] | |||
] } /> | |||
<WBTabs tabs={ [ | |||
{ 'name': 'Ala', 'isActive': true }, | |||
"Ma", | |||
@@ -0,0 +1,20 @@ | |||
import { h, Component } from 'preact'; | |||
import makeArvadosRequest from 'make-arvados-request'; | |||
class WBProjectListing extends Component { | |||
componentDidMount() { | |||
let filters = [ | |||
[ 'group_class', '=', 'project' ], | |||
[ 'owner_uuid', '=', this.props.ownerUuid ] | |||
]; | |||
let req = makeArvadosRequest(his.props.arvHost, this.props.arvToken, | |||
'/arvados/v1/groups?filters=' + encodeURIComponent(JSON.stringify(filters))) | |||
} | |||
render({ arvHost, arvToken, ownerUuid }) { | |||
return ( | |||
<div>Project Listing</div> | |||
); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
makeArvadosRequest(arvHost, arvToken, endpoint, method='GET', data=null, | |||
contentType='application/json;charset=utf-8', responseType='json') { | |||
let xhr = new XMLHttpRequest(); | |||
xhr.open(method, 'https://' + arvHost + endpoint); | |||
xhr.setRequestHeader('Authorization', 'OAuth2 ' + arvToken); | |||
if (data !== null) | |||
xhr.setRequestHeader('Content-Type', contentType); | |||
xhr.responseType = responseType; | |||
let res = new Promise((accept, reject) => { | |||
xhr.onreadystatechange = () => { | |||
if (xhr.readyState !== 4) | |||
return; | |||
if (xhr.status !== 200) | |||
reject(xhr); | |||
else | |||
accept(xhr); | |||
}; | |||
xhr.send(data); | |||
}); | |||
return res; | |||
} | |||
export default makeArvadosRequest; |
@@ -0,0 +1,73 @@ | |||
import { h, Component } from 'preact'; | |||
class WBPagination extends Component { | |||
renderVisiblePages(numPages, activePage, chunkSize, onPageChanged) { | |||
let visible = {}; | |||
let begActChnk = activePage - Math.floor(chunkSize / 2); | |||
let endActChnk = activePage + Math.floor(chunkSize / 2) + 1; | |||
for (let i = begActChnk; i < endActChnk; i++) | |||
visible[i] = true; | |||
for (let i = 0; i < chunkSize; i++) | |||
visible[i] = true; | |||
for (let i = Math.max(numPages - chunkSize, 0); i < numPages; i++) | |||
visible[i] = true; | |||
visible = Object.keys(visible).map(n => Number(n)); | |||
let res = []; | |||
let prev = 0; | |||
res.push(( | |||
<li class={ activePage === 0 ? "page-item disabled" : "page-item" }> | |||
<a class="page-link" href="#" | |||
onclick={ () => onPageChanged(activePage - 1) }>Previous</a> | |||
</li> | |||
)); | |||
for (let i in visible) { | |||
if (i > prev + 1) | |||
res.push(( | |||
<li class="page-item"> | |||
<a class="page-link" href="#" | |||
onclick={ () => onPageChanged(i - 1) }>...</a> | |||
</li> | |||
)); | |||
prev = i; | |||
res.push(( | |||
<li class={ i === activePage ? "page-item active" : "page-item" }> | |||
<a class="page-link" href="#" | |||
onclick={ () => onPageChanged(i) }>{ i + 1 }</a> | |||
</li> | |||
)); | |||
} | |||
res.push(( | |||
<li class={ activePage >= numPages - 1 ? "page-item disabled" : "page-item" }> | |||
<a class="page-link" href="#" | |||
onclick={ () => onPageChanged(activePage + 1) }>Next</a> | |||
</li> | |||
)); | |||
return res; | |||
} | |||
render({ numPages, activePage, chunkSize, onPageChanged }) { | |||
return ( | |||
<nav aria-label="Pagination"> | |||
<ul class="pagination"> | |||
{ this.renderVisiblePages(numPages, activePage, chunkSize, onPageChanged) } | |||
</ul> | |||
</nav> | |||
); | |||
} | |||
} | |||
WBPagination.defaultProps = { | |||
'chunkSize': 5 | |||
}; | |||
export default WBPagination; |
@@ -0,0 +1,26 @@ | |||
import { h, Component } from 'preact'; | |||
class WBTable extends Component { | |||
render({ columns, rows }) { | |||
return ( | |||
<table class="table table-striped table-hover"> | |||
<thead class="thead-light"> | |||
<tr> | |||
{ columns.map(c => <th>{ c }</th>) } | |||
</tr> | |||
</thead> | |||
<tbody> | |||
{ rows.map(r => ( | |||
<tr> | |||
{ columns.map((_, idx) => ( | |||
<td>{ r[idx] }</td> | |||
)) } | |||
</tr> | |||
)) } | |||
</tbody> | |||
</table> | |||
); | |||
} | |||
} | |||
export default WBTable; |