From a280791b008bd888571010936cd1e1027c783075 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Sun, 16 Dec 2018 11:36:52 +0000
Subject: [PATCH] File list view...
---
borgbutler-webapp/src/components/views/archives/FileListEntry.jsx | 19 +++
borgbutler-webapp/src/components/views/archives/FileListTable.jsx | 44 ++++++++
borgbutler-webapp/src/components/views/archives/ArchiveFileListView.jsx | 91 ++++++++++++++++++
borgbutler-webapp/src/components/views/archives/ArchiveView.jsx | 11 +
borgbutler-webapp/src/components/views/archives/FileListFilters.jsx | 91 ++++++++++++++++++
5 files changed, 254 insertions(+), 2 deletions(-)
diff --git a/borgbutler-webapp/src/components/views/archives/ArchiveFileListView.jsx b/borgbutler-webapp/src/components/views/archives/ArchiveFileListView.jsx
new file mode 100644
index 0000000..c02f657
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/archives/ArchiveFileListView.jsx
@@ -0,0 +1,91 @@
+import React from 'react'
+import {getRestServiceUrl, humanFileSize} from '../../../utilities/global';
+import ErrorAlert from '../../general/ErrorAlert';
+import {IconRefresh} from "../../general/IconComponents";
+
+class ArchiveView extends React.Component {
+
+ state = {
+ isFetching: false, activeTab: '1',
+ };
+
+ componentDidMount = () => {
+ this.fetchArchiveFileList();
+ };
+
+
+ fetchArchiveFileList = (force) => {
+ let forceReload = false;
+ if (force && confirm('Are you sure you want to reload the archive file list? This may take a long time...')) {
+ forceReload = true;
+ }
+ this.setState({
+ isFetching: true,
+ failed: false
+ });
+ fetch(getRestServiceUrl('repos/archive', {
+ repo: this.state.repoId,
+ archive: this.state.archiveId,
+ force: forceReload
+ }), {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json'
+ }
+ })
+ .then(response => response.json())
+ .then(json => {
+ this.setState({
+ isFetching: false,
+ archive: json
+ })
+ })
+ .catch(() => this.setState({isFetching: false, failed: true}));
+ };
+
+ render = () => {
+ let content = undefined;
+ let archive = this.state.archive;
+ let pageHeader = '';
+
+ if (this.state.isFetching) {
+ content = <i>Loading...</i>;
+ } else if (this.state.failed) {
+ content = <ErrorAlert
+ title={'Cannot load Repositories'}
+ description={'Something went wrong during contacting the rest api.'}
+ action={{
+ handleClick: this.fetchArchive,
+ title: 'Try again'
+ }}
+ />;
+ } else if (this.state.archive) {
+ pageHeader = <React.Fragment>
+ {archive.repoDisplayName}
+ <div
+ className={'btn btn-outline-primary refresh-button-right'}
+ onClick={this.fetchArchive.bind(this, true)}
+ >
+ <IconRefresh/>
+ </div>
+ </React.Fragment>;
+ content = <React.Fragment>
+ </React.Fragment>;
+
+ }
+ return <React.Fragment>
+ <PageHeader>
+ {pageHeader}
+ </PageHeader>
+ {content}
+ </React.Fragment>;
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.fetchArchive = this.fetchArchive.bind(this);
+ }
+}
+
+export default ArchiveView;
diff --git a/borgbutler-webapp/src/components/views/archives/ArchiveView.jsx b/borgbutler-webapp/src/components/views/archives/ArchiveView.jsx
index ce2ded3..4e3f53b 100644
--- a/borgbutler-webapp/src/components/views/archives/ArchiveView.jsx
+++ b/borgbutler-webapp/src/components/views/archives/ArchiveView.jsx
@@ -5,6 +5,7 @@
import ErrorAlert from '../../general/ErrorAlert';
import {IconRefresh} from "../../general/IconComponents";
import classNames from "classnames";
+import FileListTable from "./FileListTable";
class ArchiveView extends React.Component {
@@ -21,6 +22,10 @@
fetchArchive = (force) => {
+ let forceReload = false;
+ if (force && window.confirm('Are you sure you want to reload the archive file list? This may take a long time...')) {
+ forceReload = true;
+ }
this.setState({
isFetching: true,
failed: false
@@ -28,7 +33,7 @@
fetch(getRestServiceUrl('archives', {
repo: this.state.repoId,
archive: this.state.archiveId,
- force: force
+ force: forceReload
}), {
method: 'GET',
headers: {
@@ -170,7 +175,9 @@
</Table>
</TabPane>
<TabPane tabId={'2'}>
- Hurzel
+ <FileListTable
+ entries={this.props.entries}
+ />
</TabPane>
</TabContent>
</React.Fragment>;
diff --git a/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx b/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
new file mode 100644
index 0000000..3a1a3f3
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import Highlight from 'react-highlighter';
+
+function FileListEntry({entry, search}) {
+ return (
+ <tr>
+ <td className={'tt'}>{entry.mode}</td>
+ <td className={'tt'}><Highlight search={search}>{entry.path}</Highlight></td>
+ </tr>
+ );
+}
+
+FileListEntry.propTypes = {
+ entry: PropTypes.shape({}).isRequired,
+ search: PropTypes.string,
+};
+
+export default FileListEntry;
\ No newline at end of file
diff --git a/borgbutler-webapp/src/components/views/archives/FileListFilters.jsx b/borgbutler-webapp/src/components/views/archives/FileListFilters.jsx
new file mode 100644
index 0000000..f7d59bd
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/archives/FileListFilters.jsx
@@ -0,0 +1,91 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {FormButton, FormInput, FormLabel, FormSelect, FormOption} from '../../general/forms/FormComponents';
+import {IconRefresh} from '../../general/IconComponents';
+import I18n from '../../general/translation/I18n';
+
+function FileListFilters({loadLog, changeFilter, filters}) {
+
+ return (
+ <form
+ onSubmit={loadLog}
+ className={'form-inline'}
+ >
+ <FormLabel length={1}>
+ Filter:
+ </FormLabel>
+
+ <FormSelect
+ value={filters.threshold}
+ name={'threshold'}
+ onChange={changeFilter}
+ hint={<I18n name={'logviewer.filter.level.hint'}/>}
+ >
+ <FormOption value={'error'}/>
+ <FormOption value={'warn'}/>
+ <FormOption value={'info'}/>
+ <FormOption value={'debug'}/>
+ <FormOption value={'trace'}/>
+ </FormSelect>
+
+ <FormInput
+ value={filters.search}
+ name={'search'}
+ onChange={changeFilter}
+ fieldLength={5}
+ />
+
+ <FormSelect
+ value={filters.locationFormat}
+ name={'locationFormat'}
+ onChange={changeFilter}
+ hint={<I18n name={'logviewer.filter.location.hint'}/>}
+ >
+ <FormOption value={'none'} i18nKey={'common.none'}/>
+ <FormOption value={'short'} i18nKey={'logviewer.filter.location.option.short'}/>
+ <FormOption value={'normal'} i18nKey={'logviewer.filter.location.option.normal'}/>
+ </FormSelect>
+
+ <FormSelect
+ value={filters.showStackTrace}
+ name={'showStackTrace'}
+ onChange={changeFilter}
+ hint={<I18n name={'logviewer.filter.stacktraces.showHide.hint'}/>}
+ >
+ <FormOption value={'false'} i18nKey={'common.none'}/>
+ <FormOption value={'true'} i18nKey={'logviewer.filter.stacktraces'}/>
+ </FormSelect>
+
+ <FormSelect
+ value={filters.maxSize}
+ name={'maxSize'}
+ onChange={changeFilter}
+ hint={<I18n name={'common.limitsResultSize'} />}
+ >
+ <FormOption value={'50'} />
+ <FormOption value={'100'} />
+ <FormOption value={'500'} />
+ <FormOption value={'1000'} />
+ <FormOption value={'10000'} />
+ </FormSelect>
+ <FormButton type={'submit'} bsStyle={'primary'}>
+ <IconRefresh/>
+ </FormButton>
+ </form>
+ );
+}
+
+FileListFilters.propTypes = {
+ changeFilter: PropTypes.func.isRequired,
+ filters: PropTypes.shape({
+ threshold: PropTypes.oneOf(['error', 'warn', 'info', 'debug', 'trace']),
+ search: PropTypes.string,
+ locationFormat: PropTypes.oneOf(['none', 'short', 'normal']),
+ showStackTrace: PropTypes.oneOf(['true', 'false']),
+ maxSize: PropTypes.oneOf(['50', '100', '500', '1000', '10000']),
+ ascendingOrder: PropTypes.oneOf(['true', 'false'])
+ }).isRequired,
+ loadLog: PropTypes.func.isRequired
+};
+
+export default FileListFilters;
diff --git a/borgbutler-webapp/src/components/views/archives/FileListTable.jsx b/borgbutler-webapp/src/components/views/archives/FileListTable.jsx
new file mode 100644
index 0000000..05fbd7b
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/archives/FileListTable.jsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {Table} from 'reactstrap';
+import FileListEntry from './FileListEntry';
+
+function FileListTable({entries, search}) {
+ const lowercaseSearch = search.toLowerCase();
+ return (
+ <Table striped bordered hover size={'sm'} responsive>
+ <thead>
+ <tr>
+ <th>Mode</th>
+ <th style={{whiteSpace: 'nowrap'}}>
+ Date
+ </th>
+ <th>Path</th>
+ </tr>
+ </thead>
+ <tbody>
+ {entries
+ .filter(entry => [entry.message]
+ .join('|#|').toLowerCase()
+ .indexOf(lowercaseSearch) !== -1)
+ .map((entry, index) => <FileListEntry
+ entry={entry}
+ search={lowercaseSearch}
+ key={index}
+ />)}
+ </tbody>
+ </Table>
+ );
+}
+
+FileListTable.propTypes = {
+ entries: PropTypes.array,
+ search: PropTypes.string
+};
+
+FileListTable.defaultProps = {
+ entries: [],
+ search: ''
+};
+
+export default FileListTable;
--
Gitblit v1.10.0