Ambrosius Topor

Book Manager

Application to manage eBooks.

Book Manager: Import page

Motivation

After having bought several books, I saw the need to be able to manage and synchronize them, because it always took me too much time to do this task, by copying the relevant files manually.

Capabilities

The implementation started as a web application, but with the possibility in mind to create an Electron app.

this.add = function(item) {

    if (!(item instanceof QueueItem)) {
        throw new TypeError('Item must be an instance of QueueItem')
    }

    this.items.push(item)

    if (this.state === 'idle') {
        this.processNext();
    }

};
Command queue.

Technologies

Highlights

Transformer test in Sublime

Book Manager: Transformer test in Sublime

Mocha/Istanbul test run in Terminal

Book Manager: Mocha/Istanbul test run in Terminal

this.handle = function(item) {

    if (!(item instanceof QueueItem)) {
        throw new TypeError('Item must be instance of QueueItem, but "' + (typeof item) + '" was given')
    }

    const handleName = 'handle' + item.__proto__.constructor.name;

    if (typeof handlers[handleName] === 'function') {
        return handlers[handleName](item)
    }
    else {
        return Q.fcall(function() {
            throw new Error('No handler found to handle item of type ' + item.__proto__.constructor.name)
        })
    }

};
Queue handler.
it('should process items with handler', function() {

    const tracker = {
        fn: function() {}
    }

    const handler = {
        handle: function(item) {
            tracker.fn(item)
            return Q.fcall(function() {})
        }
    }

    const spy = expect.spyOn(tracker, 'fn')

    const queue = new Queue({handler: handler});

    const item = new JobQueueItem({
        type: 'folder_present',
        target: 'dummy'
    });

    queue.add(item);

    expect(spy).toHaveBeenCalledWith(item)

});
Queue handler test.
const BooksListPage = {

    components: {
        BooksTable: BooksTable,
        BooksCards: BooksCards,
        BooksFilter: BooksFilter,
        BooksDisplay: BooksDisplay
    },

    data: function() {
        return {
            display: 'table'
        }
    },

    template: `
        <section>

            <h1>Books</h1>

            <books-filter></books-filter>
            <books-display></books-display>

            <div class="btn-group" data-toggle="buttons">
                <label class="btn btn-default active" @click="display = 'table'">
                    <input type="radio" name="display"><i class="fa fa-th-list"></i>
                </label>
                <label class="btn btn-default" @click="display = 'cards'">
                    <input type="radio" name="display"><i class="fa fa-th-large"></i>
                </label>
            </div>

            <component :is="booksComponent" :books="$store.state.books"></component>

        </section>
    `,

    computed: {
        booksComponent: function() {
            if (this.display == 'cards') {
                return BooksCards
            }
            return BooksTable
        }
    }

}
Page component to manage rendering of books (`BooksListPage`). The book listing can be displayed in either table view or card view, using different components for the layout.

Layout

Using Gravit to work on the layout of the application.

Pages

Pages

Imports Page

Imports Page