diff --git a/htmlui/src/App.js b/htmlui/src/App.js index b259fe84d..ae76139aa 100644 --- a/htmlui/src/App.js +++ b/htmlui/src/App.js @@ -8,21 +8,18 @@ import 'react-table/react-table.css' import { SourcesTable } from "./SourcesTable"; import { PoliciesTable } from "./PoliciesTable"; import { SnapshotsTable } from "./SnapshotsTable"; +import { DirectoryObject } from "./DirectoryObject"; import Navbar from 'react-bootstrap/Navbar'; import { NavLink } from 'react-router-dom'; import Nav from 'react-bootstrap/Nav'; import Container from 'react-bootstrap/Container'; -import { withRouter } from "react-router"; - import { BrowserRouter as Router, Switch, Route, } from "react-router-dom"; -const SnapshotsTableWithRouter = withRouter(SnapshotsTable); - function App() { return ( @@ -40,21 +37,10 @@ function App() { - - - - - not implemented: directory browser - - - not implemented: file browser - - - - - - - + + + + not implemented: Status diff --git a/htmlui/src/DirectoryItems.js b/htmlui/src/DirectoryItems.js new file mode 100644 index 000000000..0e847565f --- /dev/null +++ b/htmlui/src/DirectoryItems.js @@ -0,0 +1,81 @@ +import React, { Component } from 'react'; +import ReactTable from 'react-table'; +import { Link } from "react-router-dom"; + +import { + sizeDisplayName, + objectLink, +} from './uiutil'; + +function objectName(name, typeID) { + if (typeID === "d") { + return name + "/"; + } + + return name +} + +function sizeInfo(item) { + if (item.size) { + return sizeDisplayName(item.size); + } + const summ = item.summ; + if (!summ) { + return ""; + } + return sizeDisplayName(summ.size) + ", " + summ.files + " files, " + summ.dirs + " dirs"; +} + +function sizeForSorting(item) { + if (item.size) { + return item.size; + } + + if (item.summ && item.summ.size) { + return item.summ.size; + } + + return 0; +} + +function sizeSortMethod(a, b, desc) { + const l = sizeForSorting(a); + const r = sizeForSorting(b); + + if (l < r) { + return -1; + } + if (l > r) { + return 1; + } + return 0; +} + +function directoryLinkOrDownload(x) { + if (x.obj.startsWith("k")) { + return {objectName(x.name, x.type)}; + } + + return {x.name}; +} + +export class DirectoryItems extends Component { + render() { + const columns = [{ + id: "name", + Header: 'Name', + accessor: x => directoryLinkOrDownload(x), + }, { + id: "mtime", + accessor: "mtime", + Header: "Last Mod", + }, { + id: "size", + accessor: x => sizeInfo(x), + Header: "Size", + sortMethod: sizeSortMethod, + }] + + return ; + } +} diff --git a/htmlui/src/DirectoryObject.js b/htmlui/src/DirectoryObject.js new file mode 100644 index 000000000..a9fc064c3 --- /dev/null +++ b/htmlui/src/DirectoryObject.js @@ -0,0 +1,61 @@ +import React, { Component } from 'react'; +import axios from 'axios'; + +import { DirectoryItems } from "./DirectoryItems"; +import Button from 'react-bootstrap/Button'; +import Spinner from 'react-bootstrap/Spinner'; + +export class DirectoryObject extends Component { + constructor() { + super(); + + this.state = { + items: [], + isLoading: false, + error: null, + }; + } + + componentDidMount() { + this.fetchDirectory(this.props); + } + + fetchDirectory(props) { + console.log('fetching props:', props); + let oid = props.match.params.oid; + + this.setState({ + isLoading: true, + }); + axios.get('/api/v1/objects/' + oid).then(result => { + this.setState({ + items: result.data.entries, + isLoading: false, + }); + }).catch(error => this.setState({ + error, + isLoading: false + })); + } + + componentWillReceiveProps(props) { + this.fetchDirectory(props); + } + + render() { + let { items, isLoading, error } = this.state; + if (error) { + return ERROR: {error.message}; + } + if (isLoading) { + return ; + } + + return + + Back + + + + } +} diff --git a/htmlui/src/PoliciesTable.js b/htmlui/src/PoliciesTable.js index 9713f7fb4..95fa7ac98 100644 --- a/htmlui/src/PoliciesTable.js +++ b/htmlui/src/PoliciesTable.js @@ -1,6 +1,5 @@ import React, { Component } from 'react'; import ReactTable from 'react-table'; -import Button from 'react-bootstrap/Button'; import axios from 'axios'; import { @@ -67,11 +66,6 @@ export class PoliciesTable extends Component { accessor: x => timesOfDayDisplayName(x.policy.scheduling.timesOfDay), }] - return - - flat button - - ; - + return ; } } diff --git a/htmlui/src/SnapshotsTable.js b/htmlui/src/SnapshotsTable.js index 8a047b584..e9e094994 100644 --- a/htmlui/src/SnapshotsTable.js +++ b/htmlui/src/SnapshotsTable.js @@ -58,7 +58,6 @@ export class SnapshotsTable extends Component { selectedSnapshot: null, }); const u = '/api/v1/snapshots?host=' + q.host + '&userName=' + q.userName + '&path=' + q.path; - console.log('u', u); axios.get(u).then(result => { console.log('got snapshots', result.data); this.setState({ diff --git a/htmlui/src/SourcesTable.js b/htmlui/src/SourcesTable.js index f0b7edf31..ae1b78f81 100644 --- a/htmlui/src/SourcesTable.js +++ b/htmlui/src/SourcesTable.js @@ -25,7 +25,7 @@ export class SourcesTable extends Component { selectedUser: allUsers, }; } - ; + componentDidMount() { this.setState({ isLoading: true }); axios.get('/api/v1/sources').then(result => { @@ -54,6 +54,7 @@ export class SourcesTable extends Component { hostClicked(h) { alert('host clicked ' + h); } + render() { let { sources, isLoading, error } = this.state; if (error) { @@ -124,7 +125,7 @@ export class SourcesTable extends Component { this.selectHost(allHosts)}>(all) {uniqueHosts.map(v => this.selectHost(v)}>{v})} - + @@ -139,7 +140,7 @@ export class SourcesTable extends Component { - + ; diff --git a/htmlui/src/uiutil.js b/htmlui/src/uiutil.js index e6fde0bba..072c5af44 100644 --- a/htmlui/src/uiutil.js +++ b/htmlui/src/uiutil.js @@ -29,6 +29,9 @@ function toDecimalUnitString(f, thousand, prefixes, suffix) { export function sizeDisplayName(s) { + if (s === undefined) { + return ""; + } return toDecimalUnitString(s, 1000, base10UnitPrefixes, "B"); } @@ -62,5 +65,5 @@ export function objectLink(n) { if (n.startsWith("k")) { return "/snapshots/dir/" + n; } - return "/snapshots/file/" + n; + return "/api/v1/objects/" + n; } \ No newline at end of file
not implemented: directory browser
not implemented: file browser
not implemented: Status
ERROR: {error.message}