import/export

This commit is contained in:
j 2014-05-17 10:17:34 +02:00
parent dbfdd50a29
commit bceb5e6d4a
14 changed files with 450 additions and 148 deletions

View file

@ -284,6 +284,8 @@
]}, ]},
{"id": "users", "title": "Users"}, {"id": "users", "title": "Users"},
{"id": "devices", "title": "Devices"}, {"id": "devices", "title": "Devices"},
{"id": "import", "title": "Import"},
{"id": "export", "title": "Export"},
{"id": "notifications", "title": "Notifications"}, {"id": "notifications", "title": "Notifications"},
{"id": "transfers", "title": "Transfers"}, {"id": "transfers", "title": "Transfers"},
{"id": "gettingstarted", "title": "Getting Started"}, {"id": "gettingstarted", "title": "Getting Started"},

View file

@ -174,6 +174,7 @@ class List(db.Model):
for item_id in items: for item_id in items:
i = Item.get(item_id) i = Item.get(item_id)
i.update_lists() i.update_lists()
db.session.add(i)
db.session.commit() db.session.commit()
if self.user_id == settings.USER_ID: if self.user_id == settings.USER_ID:
Changelog.record(self.user, 'addlistitems', self.name, items) Changelog.record(self.user, 'addlistitems', self.name, items)
@ -189,6 +190,8 @@ class List(db.Model):
for item_id in items: for item_id in items:
i = Item.get(item_id) i = Item.get(item_id)
i.update_lists() i.update_lists()
db.session.add(i)
db.session.commit()
db.session.commit() db.session.commit()
if self.user_id == settings.USER_ID: if self.user_id == settings.USER_ID:
Changelog.record(self.user, 'removelistitems', self.name, items) Changelog.record(self.user, 'removelistitems', self.name, items)

View file

@ -19,7 +19,6 @@ oml.Preferences = (function() {
set[key] = value; set[key] = value;
} }
}); });
if (Ox.len(set)) { if (Ox.len(set)) {
oml.api.setPreferences(set); oml.api.setPreferences(set);
Ox.forEach(set, function(value, key) { Ox.forEach(set, function(value, key) {

View file

@ -18,23 +18,38 @@ oml.ui.appPanel = function() {
}) })
.bindEvent({ .bindEvent({
oml_page: function(data) { oml_page: function(data) {
setPage(data.value); setPage(data.value, data.previousValue);
} }
}); });
setPage(ui.page); setPage(ui.page);
function setPage(page) { function setPage(page, previousPage) {
// close dialogs // close dialogs
$('.OxDialog:visible').each(function() { if (
Ox.UI.elements[$(this).data('oxid')].close(); !Ox.contains(['import', 'export'], page)
}); || !Ox.contains(['import', 'export'], previousPage)
) {
$('.OxDialog:visible').each(function() {
Ox.UI.elements[$(this).data('oxid')].close();
});
}
// open dialog // open dialog
if (Ox.contains([ if (Ox.contains([
'welcome', 'app', 'preferences', 'users', 'welcome', 'app', 'preferences', 'users',
'notifications', 'transfers', 'help' 'notifications', 'transfers', 'help'
], page)) { ], page)) {
oml.$ui[page + 'Dialog'] = oml.ui[page + 'Dialog']().open(); oml.$ui[page + 'Dialog'] = oml.ui[page + 'Dialog']().open();
} else if (Ox.contains(['import', 'export'], page)) {
if (
oml.$ui.importExportDialog
&& oml.$ui.importExportDialog.is(':visible')
) {
Ox.print('AAAAAAAA')
oml.$ui.importExportDialog.select(page);
} else {
oml.$ui.importExportDialog = oml.ui.importExportDialog(page).open();
}
} }
} }

View file

@ -10,7 +10,7 @@ oml.ui.folders = function() {
that = Ox.Element() that = Ox.Element()
.css({ .css({
//overflowX: 'hidden', overflowX: 'hidden',
//overflowY: 'auto', //overflowY: 'auto',
}) })
.bindEvent({ .bindEvent({

View file

@ -1,117 +0,0 @@
'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

@ -0,0 +1,391 @@
'use strict';
oml.ui.importExportDialog = function(selected) {
var ui = oml.user.ui,
username = oml.user.preferences.username,
$bar = Ox.Bar({size: 24}),
$buttons = Ox.ButtonGroup({
buttons: [
{id: 'import', title: Ox._('Import Books')},
{id: 'export', title: Ox._('Export Books')}
],
min: 1,
max: 1,
selectable: true,
selected: selected
})
.css({
width: '768px',
padding: '4px 0',
textAlign: 'center'
})
.bindEvent({
change: function(data) {
oml.UI.set({page: data.value});
}
})
.appendTo($bar),
$innerPanel = Ox.SlidePanel({
elements: [
{id: 'import', element: Ox.Element()},
{id: 'export', element: Ox.Element()}
],
orientation: 'horizontal',
selected: selected,
size: 512
}),
$outerPanel = Ox.SplitPanel({
elements: [
{element: $bar, size: 24},
{element: $innerPanel}
],
orientation: 'vertical'
}),
that = Ox.Dialog({
buttons: [
Ox.Button({
id: 'close',
title: Ox._('Close')
})
.bindEvent({
click: function() {
that.close();
}
})
],
closeButton: true,
content: Ox.LoadingScreen().start(),
height: 144,
removeOnClose: true,
title: Ox._('Import & Export Books'),
width: 512
})
.bindEvent({
close: function() {
if (Ox.contains(['import', 'export'], ui.page)) {
oml.UI.set({page: ''});
}
},
oml_page: function(data) {
if (Ox.contains(['import', 'export'], data.value)) {
selected = data.value;
$buttons.options({selected: selected});
$innerPanel.options({selected: selected});
}
}
}),
$label = {},
$activityButton = {},
$progress = {},
$status = {},
$progressButton = {};
oml.getUsersAndLists(function() {
oml.api.getActivity(function(result) {
var isActive = !Ox.isEmpty(result.data),
activity = result.data.activity;
/*
result.data = {
path: '/Users/rolux/Desktop/Books',
status: {},
progress: [0,42]
};
*/
Ox.print(result.data, '!!!!!!!!')
$innerPanel
.replaceElement(0,
activity == 'import' ? renderActivity(result.data)
: renderForm('import', isActive)
)
.replaceElement(1,
activity == 'export' ? renderActivity(result.data)
: renderForm('export', isActive)
);
that.options({content: $outerPanel});
});
});
function getListItems(selected) {
var lists = ui._lists.filter(function(list) {
return list.user == username && list.type != 'library' && (
selected == 'export' || list.type == 'static'
);
});
return [
{id: ':', title: Ox._('Library')}
].concat(
lists.length ? [{}] : []
).concat(
lists.map(function(list) {
return {id: list.id, title: list.name};
})
).concat(selected == 'import' ? [
{},
{id: '', title: Ox._('New List...')}
] : []);
}
function getListNames() {
return ui._lists.filter(function(list) {
return list.user == username;
}).map(function(list) {
return list.name;
});
}
function renderActivity(data) {
var $element = Ox.Element(),
$title = $('<div>')
.addClass('OxSelectable')
.css({
margin: '16px 16px 4px 16px',
width: '480px',
height: '16px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
})
.html(
Ox._(data.activity == 'import' ? 'Import from' : 'Export to')
+ ' <span class="OxMonospace">' + data.path + '</span>'
)
.appendTo($element);
$progress[data.activity] = Ox.Progressbar({
progress: -1,
showTooltips: true,
width: 480
})
.css({margin: '4px 16px'})
.appendTo($element);
$status[data.activity] = $('<div>')
.addClass('OxSelectable')
.css({
margin: '6px 16px 4px 16px',
height: '16px'
})
.appendTo($element);
$progressButton[data.activity] = Ox.Button({
title: '',
width: 128
})
.css({
position: 'absolute',
right: '16px',
bottom: '16px'
})
.bindEvent({
click: function() {
if (this.options('title') == Ox._('Done')) {
$innerPanel.replaceElement(0, renderForm(data.activity));
} else {
oml.api[
data.activity == 'import' ? 'cancelImport' : 'cancelExport'
](function() {
// ...
});
}
}
})
.appendTo($element);
if (data.progress) {
setProgress(data);
setStatus(data);
setButton(data);
}
return $element;
}
function renderForm(selected, isActive) {
var $element = Ox.Element(),
$form = Ox.Form({
items: selected == 'import' ? [
Ox.Input({
changeOnKeypress: true,
id: 'path',
label: 'Source Path',
labelWidth: 128,
width: 480
}),
Ox.SelectInput({
id: 'list',
inputValue: oml.validateName(Ox._('Untitled'), getListNames()),
inputWidth: 224,
items: getListItems('import'),
label: 'Destination',
labelWidth: 128,
max: 1,
min: 1,
value: ':',
width: 480
}),
Ox.Select({
id: 'mode',
items: [
{id: 'copy', title: Ox._('Copy files')},
{id: 'move', title: Ox._('Move files')}
],
label: Ox._('Import Mode'),
labelWidth: 128,
width: 480
})
] : [
Ox.Input({
changeOnKeypress: true,
id: 'path',
label: 'Destination Path',
labelWidth: 128,
width: 480
}),
Ox.Select({
id: 'list',
items: getListItems('export'),
label: 'Source',
labelWidth: 128,
value: ':',
width: 480
}),
Ox.Select({
id: 'mode',
items: [
{id: 'keep', title: Ox._('Keep existing files')},
{id: 'remove', title: Ox._('Remove existing files')}
],
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, getListNames()))
}
}
$activityButton[selected].options({
disabled: !values.path || !values.list
});
}
})
.appendTo($element);
$label[selected] = Ox.Label({
//textAlign: 'center',
title: Ox._(
'Waiting for '
+ (selected == 'import' ? 'export' : 'import')
+ ' to finish...'
),
width: 344
})
.css({
position: 'absolute',
bottom: '16px',
left: '16px'
})
[isActive ? 'show' : 'hide']()
.appendTo($element);
$activityButton[selected] = Ox.Button({
disabled: true,
id: 'import',
title: Ox._(selected == 'import' ? 'Import' : 'Export'),
width: 128
})
.css({
position: 'absolute',
right: '16px',
bottom: '16px'
})
.bindEvent({
click: function() {
var data = $form.values();
$innerPanel.replaceElement(0,
renderActivity({
activity: 'import',
path: data.path,
progress: [0, 0]
})
);
$label['export'].show();
oml.api.import({
list: data.list, // FIXME: WRONG for Library
mode: data.mode,
path: data.path,
}, function() {
// ...
})
}
})
.appendTo($element);
return $element;
}
function setButton(data) {
$progressButton[data.activity].options({
title: !data.status ? Ox._(
data.activity == 'import' ? 'Cancel Import' : 'Cancel Export'
) : Ox._('Done')
});
}
function setProgress(data) {
Ox.print('SET PROGRESS', data, $progress)
var progress = data.status ? 1
: !data.progress[0] || !data.progress[1] ? -1
: data.progress[0] / data.progress[1];
$progress[data.activity].options({progress: progress})
}
function setStatus(data) {
// FIXME: LOCALIZATION
var total = Ox.formatCount(data.progress[1], 'book').replace(/$no /, 'No'),
status = data.status && data.status.code
? (
data.status.code == 200 ? (
data.progress[1]
? 'Done. ' + total + ' ' + (selected == 'import' ? 'imported' : 'exported.')
: Ox._('No books found.')
)
: data.status.code == 404 ? Ox._((
selected == 'import' ? 'Source' : 'Destination'
) + ' path not found.')
: Ox._((selected == 'import' ? 'Import' : 'Export') + 'failed.')
)
: !data.progress[0] && data.progress[1] ? Ox._('Scanning: {0} found.', [total])
: data.progress[0] ? Ox._(selected == 'import' ? 'Importing:' : 'Exporting')
+ ' ' + Ox._('{0} of {1}', [data.progress[0], total])
: '';
$status[data.activity].html(status);
}
that.select = function(selected_) {
selected = selected_;
$buttons.options({selected: selected});
$innerPanel.options({selected: selected});
return that;
};
oml.bindEvent({
activity: function(data) {
Ox.print('activity', arguments);
setProgress(data);
setStatus(data);
setButton(data);
}
});
return that;
};

View file

@ -247,6 +247,10 @@ oml.ui.infoView = function(identifyData) {
keys: [] keys: []
}, function(result) { }, function(result) {
if (!identifyData && ui.item != id) {
return;
}
if (result) { if (result) {
data = result.data; data = result.data;
} }

View file

@ -371,7 +371,9 @@ oml.ui.mainMenu = function() {
} else if (id == 'deletelist') { } else if (id == 'deletelist') {
oml.ui.deleteListDialog().open(); oml.ui.deleteListDialog().open();
} else if (id == 'import') { } else if (id == 'import') {
oml.ui.importDialog().open(); oml.UI.set({page: 'import'});
} else if (id == 'export') {
oml.UI.set({page: 'export'});
} else if (id == 'selectall') { } else if (id == 'selectall') {
oml.$ui.list.selectAll(); oml.$ui.list.selectAll();
} else if (id == 'selectnone') { } else if (id == 'selectnone') {
@ -548,11 +550,11 @@ oml.ui.mainMenu = function() {
items: [ items: [
{ {
id: 'import', id: 'import',
title: Ox._('Import Books...') title: Ox._(oml.user.importing ? 'Importing Books...' : 'Import Books...') // FIXME
}, },
{ {
id: 'export', id: 'export',
title: Ox._('Export Books...') title: Ox._(oml.user.exporting ? 'Exporting Books...' : 'Export Books...') // FIXME
}, },
{}, {},
{ {

View file

@ -37,16 +37,18 @@
config: data.config, config: data.config,
user: data.user user: data.user
}); });
// make sure all valid ui settings are present ['preferences', 'ui'].forEach(function(key) {
oml.user.ui = Ox.extend( // make sure all valid settings are present
Ox.clone(data.config.user.ui, true), oml.user[key] = Ox.extend(
oml.user.ui Ox.clone(data.config.user[key], true),
); oml.user[key]
// make sure no invalid ui settings are present );
Object.keys(oml.user.ui).forEach(function(key) { // make sure no invalid settings are present
if (Ox.isUndefined(oml.config.user.ui[key])) { Object.keys(oml.user[key]).forEach(function(key_) {
delete oml.user.ui[key]; if (Ox.isUndefined(oml.config.user[key][key_])) {
} delete oml.user[key][key_];
}
});
}); });
// TODO: make sure listView, listSort and itemView are valid // TODO: make sure listView, listSort and itemView are valid
Ox.extend(oml.config, { Ox.extend(oml.config, {

View file

@ -25,7 +25,7 @@ oml.ui.preferencesDialog = function() {
{ {
id: 'libraryPath', id: 'libraryPath',
title: 'Library Path', title: 'Library Path',
value: preferences.libaryPath, value: preferences.libraryPath,
help: 'The directory in which your "Books" folder is located. This is where your media files are stored. It can be on your local machine, but just as well on an external drive or networked volume.' help: 'The directory in which your "Books" folder is located. This is where your media files are stored. It can be on your local machine, but just as well on an external drive or networked volume.'
}, },
{ {
@ -366,7 +366,7 @@ oml.ui.preferencesDialog = function() {
? Ox.Input({ ? Ox.Input({
height: 328, height: 328,
type: 'textarea', type: 'textarea',
value: item.value, value: oml.user.preferences[item.id] || item.value,
width: 400 width: 400
}) })
: Ox.isBoolean(item.value) : Ox.isBoolean(item.value)
@ -379,7 +379,7 @@ oml.ui.preferencesDialog = function() {
label: Ox._(item.title), label: Ox._(item.title),
labelWidth: 128, labelWidth: 128,
placeholder: item.placeholder || '', placeholder: item.placeholder || '',
value: item.value || '', value: oml.user.preferences[item.id] || item.value || '',
width: 384 - !!item.unit * 48 width: 384 - !!item.unit * 48
}) })

View file

@ -174,8 +174,6 @@ oml.ui.usersDialog = function() {
function renderUser(user) { function renderUser(user) {
Ox.print('renderUSER', user)
var $user = Ox.Element(), var $user = Ox.Element(),
$form = Ox.Element() $form = Ox.Element()
@ -521,6 +519,7 @@ oml.ui.usersDialog = function() {
} }
function updateUsers(callback) { function updateUsers(callback) {
oml.api.getUsers(function(result) { oml.api.getUsers(function(result) {
users = result.data.users; users = result.data.users;
@ -580,6 +579,7 @@ oml.ui.usersDialog = function() {
callback && callback(); callback && callback();
}); });
} }
that.update = function() { that.update = function() {

View file

@ -727,6 +727,7 @@ oml.getListData = function(list) {
oml.getListFoldersHeight = function() { oml.getListFoldersHeight = function() {
var ui = oml.user.ui; var ui = oml.user.ui;
return Object.keys(ui.showFolder).reduce(function(value, id, index) { return Object.keys(ui.showFolder).reduce(function(value, id, index) {
Ox.print('WTF WTF', index)
var items = oml.$ui.folderList[index].options('items').length; var items = oml.$ui.folderList[index].options('items').length;
return value + 16 + ui.showFolder[id] * (1 + items) * 16; return value + 16 + ui.showFolder[id] * (1 + items) * 16;
}, 16); }, 16);
@ -828,15 +829,15 @@ oml.resizeListFolders = function() {
var width = oml.getListFoldersWidth(), var width = oml.getListFoldersWidth(),
columnWidth = width - 58; columnWidth = width - 58;
oml.$ui.librariesList oml.$ui.librariesList
.resizeColumn('title', columnWidth) .resizeColumn('name', columnWidth)
.css({width: width + 'px'}); .css({width: width + 'px'});
Ox.forEach(oml.$ui.folder, function($folder, index) { Ox.forEach(oml.$ui.folder, function($folder, index) {
$folder.css({width: width + 'px'}); $folder.css({width: width + 'px'});
oml.$ui.libraryList[index] oml.$ui.libraryList[index]
.resizeColumn('title', columnWidth) .resizeColumn('name', columnWidth)
.css({width: width + 'px'}); .css({width: width + 'px'});
oml.$ui.folderList[index] oml.$ui.folderList[index]
.resizeColumn('title', columnWidth) .resizeColumn('name', columnWidth)
.css({width: width + 'px'}); .css({width: width + 'px'});
}); });
oml.$ui.librariesList oml.$ui.librariesList

View file

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