Ambrosius Topor

Book Manager

Application to manage eBooks.

Book Manager: Import page


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.


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')


    if (this.state === 'idle') {

Command queue.



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' +;

    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 ' +

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

    const tracker = {
        fn: function() {}

    const handler = {
        handle: function(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 handler test.
const BooksListPage = {

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

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

    template: `



            <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 class="btn btn-default" @click="display = 'cards'">
                    <input type="radio" name="display"><i class="fa fa-th-large"></i>

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


    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.


Using Gravit to work on the layout of the application.



Imports Page

Imports Page