import items

This commit is contained in:
j 2014-05-16 16:30:16 +02:00
parent e41942ea99
commit 823ae2a676
11 changed files with 181 additions and 36 deletions

5
README
View file

@ -21,6 +21,11 @@ you need a working python 2.7.x installation and the following packages:
python-simplejson python-lxml python-simplejson python-lxml
pip install -r requirements.txt pip install -r requirements.txt
On Linux you need to always install:
apt-get install \
python-imaging python-lxml ghostscript
== Development == == Development ==
mkdir client mkdir client

View file

@ -56,6 +56,15 @@ class Changelog(db.Model):
def timestamp(self): def timestamp(self):
return self.created.strftime('%s') return self.created.strftime('%s')
@classmethod
def apply_changes(cls, user, changes):
for change in changes:
if not Changelog.apply_change(user, change):
print 'FAIL', change
break
return False
return True
@classmethod @classmethod
def apply_change(cls, user, change, rebuild=False): def apply_change(cls, user, change, rebuild=False):
revision, timestamp, sig, data = change revision, timestamp, sig, data = change

View file

@ -183,6 +183,8 @@ actions.register(scan, cache=False)
@returns_json @returns_json
def _import(request): def _import(request):
state.main.add_callback(state.websockets[0].put, json.dumps(['import', {}])) data = json.loads(request.form['data']) if 'data' in request.form else {}
print 'api.import', data
state.main.add_callback(state.websockets[0].put, json.dumps(['import', data]))
return {} return {}
actions.register(_import, 'import', cache=False) actions.register(_import, 'import', cache=False)

View file

@ -12,13 +12,15 @@ from app import app
import settings import settings
from settings import db from settings import db
from item.models import File from item.models import File
from user.models import User from user.models import User, List
from changelog import Changelog from changelog import Changelog
import media import media
from websocket import trigger_event from websocket import trigger_event
extensions = ['epub', 'pdf', 'txt']
def remove_missing(): def remove_missing():
dirty = False dirty = False
with app.app_context(): with app.app_context():
@ -49,7 +51,6 @@ def run_scan():
prefix += '/' prefix += '/'
user = User.get_or_create(settings.USER_ID) user = User.get_or_create(settings.USER_ID)
assert isinstance(prefix, unicode) assert isinstance(prefix, unicode)
extensions = ['pdf', 'epub', 'txt']
books = [] books = []
for root, folders, files in os.walk(prefix): for root, folders, files in os.walk(prefix):
for f in files: for f in files:
@ -62,8 +63,7 @@ def run_scan():
books.append(f) books.append(f)
trigger_event('scan', { trigger_event('scan', {
'path': prefix, 'progress': [0, len(books)],
'files': len(books)
}) })
position = 0 position = 0
added = 0 added = 0
@ -96,29 +96,37 @@ def run_scan():
item.scrape() item.scrape()
added += 1 added += 1
trigger_event('scan', { trigger_event('scan', {
'position': position,
'length': len(books),
'path': path,
'progress': position/len(books),
'added': added, 'added': added,
'progress': [position, len(books)],
'path': path,
}) })
trigger_event('scan', { trigger_event('scan', {
'progress': 1, 'progress': [position, len(books)],
'added': added, 'added': added,
'done': True 'status': {'code': 200, 'text': ''}
}) })
def run_import(): def run_import(options=None):
options = options or {}
with app.app_context(): with app.app_context():
prefs = settings.preferences prefs = settings.preferences
prefix = os.path.expanduser(prefs['importPath']) prefix = options.get('path', os.path.expanduser(prefs['importPath']))
prefix_books = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') prefix_books = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/')
prefix_imported = os.path.join(prefix_books, 'Imported/') prefix_imported = os.path.join(prefix_books, 'Imported/')
if not prefix[-1] == '/': if not prefix[-1] == '/':
prefix += '/' prefix += '/'
if not os.path.exists(prefix):
trigger_event('import', {
'progress': [0, 0],
'status': {'code': 404, 'text': 'path not found'}
})
user = User.get_or_create(settings.USER_ID) user = User.get_or_create(settings.USER_ID)
listname = options.get('list')
if listname:
listitems = []
assert isinstance(prefix, unicode) assert isinstance(prefix, unicode)
extensions = ['pdf', 'epub', 'txt']
books = [] books = []
for root, folders, files in os.walk(prefix): for root, folders, files in os.walk(prefix):
for f in files: for f in files:
@ -131,8 +139,7 @@ def run_import():
books.append(f) books.append(f)
trigger_event('import', { trigger_event('import', {
'path': prefix, 'progress': [0, len(books)],
'files': len(books)
}) })
position = 0 position = 0
added = 0 added = 0
@ -145,7 +152,10 @@ def run_import():
f_import = f f_import = f
f = f.replace(prefix, prefix_imported) f = f.replace(prefix, prefix_imported)
ox.makedirs(os.path.dirname(f)) ox.makedirs(os.path.dirname(f))
if options.get('mode') == 'move':
shutil.move(f_import, f) shutil.move(f_import, f)
else:
shutil.copy(f_import, f)
path = f[len(prefix_books):] path = f[len(prefix_books):]
data = media.metadata(f) data = media.metadata(f)
ext = f.split('.')[-1] ext = f.split('.')[-1]
@ -167,16 +177,19 @@ def run_import():
item.meta['mainid']: item.meta[item.meta['mainid']] item.meta['mainid']: item.meta[item.meta['mainid']]
}) })
item.scrape() item.scrape()
if listname:
listitems.append(item.id)
added += 1 added += 1
trigger_event('import', { trigger_event('import', {
'position': position, 'progress': [position, len(books)],
'length': len(books),
'path': path, 'path': path,
'progress': position/len(books),
'added': added, 'added': added,
}) })
if listname:
l = List.get_or_create(settings.USER_ID, listname)
l.add_items(listitems)
trigger_event('import', { trigger_event('import', {
'progress': 1, 'progress': [position, len(books)],
'status': {'code': 200, 'text': ''},
'added': added, 'added': added,
'done': True
}) })

View file

@ -46,6 +46,8 @@ def info(epub):
isbn = extract_isbn(text) isbn = extract_isbn(text)
if isbn: if isbn:
data['isbn'] = isbn data['isbn'] = isbn
if 'date' in data and 'T' in data['date']:
data['date'] = data['date'].split('T')[0]
return data return data
def extract_text(path): def extract_text(path):

View file

@ -29,9 +29,8 @@ def api_pullChanges(app, remote_id, user_id=None, from_=None, to=None):
def api_pushChanges(app, user_id, changes): def api_pushChanges(app, user_id, changes):
user = User.get(user_id) user = User.get(user_id)
for change in changes: if not Changelog.apply_changes(user, changes):
if not Changelog.apply_change(user, change): print 'FAILED TO APPLY CHANGE'
print 'FAILED TO APPLY CHANGE', change
state.nodes.queue(user_id, 'pullChanges') state.nodes.queue(user_id, 'pullChanges')
return False return False
return True return True

View file

@ -164,12 +164,7 @@ class Node(object):
changes = self.request('pullChanges', from_revision) changes = self.request('pullChanges', from_revision)
if not changes: if not changes:
return False return False
for change in changes: return Changelog.apply_changes(self.user, changes)
if not Changelog.apply_change(self.user, change):
print 'FAIL', change
break
return False
return True
def pushChanges(self, changes): def pushChanges(self, changes):
print 'pushing changes to', self.user_id, changes print 'pushing changes to', self.user_id, changes

View file

@ -33,7 +33,7 @@ class Background:
if action == 'ping': if action == 'ping':
self.post(['pong', data]) self.post(['pong', data])
elif action == 'import': elif action == 'import':
item.scan.run_import() item.scan.run_import(data)
elif action == 'scan': elif action == 'scan':
item.scan.run_scan() item.scan.run_scan()
elif action == 'update': elif action == 'update':

117
static/js/importDialog.js Normal file
View file

@ -0,0 +1,117 @@
'use strict';
oml.ui.importDialog = function() {
var ui = oml.user.ui,
username = oml.user.preferences.username,
lists = ui._lists.filter(function(list) {
return list.user == username && list.type == 'static';
}),
items = [
{id: ':', title: Ox._('Library')}
].concat(
lists.length ? [{}] : []
).concat(
lists.map(function(list) {
return {id: list.id, title: list.name};
})
).concat([
{},
{id: '', title: Ox._('New List...')}
]),
listNames = ui._lists.filter(function(list) {
return list.user == username;
}).map(function(list) {
return list.name;
}),
$form = Ox.Form({
items: [
Ox.Input({
changeOnKeypress: true,
id: 'path',
label: 'Source Path',
labelWidth: 128,
width: 480
}),
Ox.SelectInput({
id: 'list',
inputValue: oml.validateName(Ox._('Untitled'), listNames),
inputWidth: 224,
items: items,
label: 'Destination',
labelWidth: 128,
max: 1,
min: 1,
value: ':',
width: 480
}),
Ox.Select({
id: 'action',
items: [
{id: 'copy', title: Ox._('Keep files in source path')},
{id: 'move', title: Ox._('Remove files from source path')}
],
label: Ox._('Import Mode'),
labelWidth: 128,
width: 480
})
]
})
.css({margin: '16px'})
.bindEvent({
change: function(data) {
var values = $form.values();
Ox.print('FORM CHANGE', data);
if (data.id == 'list') {
// FIXME: WRONG
if (data.data.value[0] != ':') {
$form.values('list', oml.validateName(data.data.value, listNames))
}
}
that[
values.path && values.list ? 'enableButton' : 'disableButton'
]('import');
}
}),
that = Ox.Dialog({
buttons: [
Ox.Button({
id: 'dontimport',
title: Ox._('No, Don\'t Import')
})
.bindEvent({
click: function() {
that.close();
}
}),
Ox.Button({
disabled: true,
id: 'import',
title: Ox._('Yes, Import')
})
.bindEvent({
click: function() {
var data = $form.values();
oml.api.import({
path: data.path,
list: data.list == ':' ? null : data.list
}, function() {
// ...
})
that.close();
}
})
],
content: $form,
height: 128,
title: Ox._('Import Books'),
width: 512
});
return that;
};

View file

@ -370,6 +370,8 @@ oml.ui.mainMenu = function() {
oml.ui.listDialog.open(); oml.ui.listDialog.open();
} else if (id == 'deletelist') { } else if (id == 'deletelist') {
oml.ui.deleteListDialog().open(); oml.ui.deleteListDialog().open();
} else if (id == 'import') {
oml.ui.importDialog().open();
} else if (id == 'selectall') { } else if (id == 'selectall') {
oml.$ui.list.selectAll(); oml.$ui.list.selectAll();
} else if (id == 'selectnone') { } else if (id == 'selectnone') {
@ -545,11 +547,11 @@ oml.ui.mainMenu = function() {
title: Ox._('Edit'), title: Ox._('Edit'),
items: [ items: [
{ {
id: 'importitems', id: 'import',
title: Ox._('Import Books...') title: Ox._('Import Books...')
}, },
{ {
id: 'exportitems', id: 'export',
title: Ox._('Export Books...') title: Ox._('Export Books...')
}, },
{}, {},

View file

@ -25,6 +25,7 @@
"gridView.js", "gridView.js",
"iconDialog.js", "iconDialog.js",
"identifyDialog.js", "identifyDialog.js",
"importDialog.js",
"info.js", "info.js",
"infoView.js", "infoView.js",
"itemInnerPanel.js", "itemInnerPanel.js",