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