mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
16.36.2018 a280791b008bd888571010936cd1e1027c783075
File list view...
4 files added
1 files modified
256 ■■■■■ changed files
borgbutler-webapp/src/components/views/archives/ArchiveFileListView.jsx 91 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/ArchiveView.jsx 11 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/FileListEntry.jsx 19 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/FileListFilters.jsx 91 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/FileListTable.jsx 44 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/archives/ArchiveFileListView.jsx
New file
@@ -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;
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>;
borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
New file
@@ -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;
borgbutler-webapp/src/components/views/archives/FileListFilters.jsx
New file
@@ -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;
borgbutler-webapp/src/components/views/archives/FileListTable.jsx
New file
@@ -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;