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": "devices", "title": "Devices"},
{"id": "import", "title": "Import"},
{"id": "export", "title": "Export"},
{"id": "notifications", "title": "Notifications"},
{"id": "transfers", "title": "Transfers"},
{"id": "gettingstarted", "title": "Getting Started"},

View file

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

View file

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

View file

@ -18,23 +18,38 @@ oml.ui.appPanel = function() {
})
.bindEvent({
oml_page: function(data) {
setPage(data.value);
setPage(data.value, data.previousValue);
}
});
setPage(ui.page);
function setPage(page) {
function setPage(page, previousPage) {
// close dialogs
$('.OxDialog:visible').each(function() {
Ox.UI.elements[$(this).data('oxid')].close();
});
if (
!Ox.contains(['import', 'export'], page)
|| !Ox.contains(['import', 'export'], previousPage)
) {
$('.OxDialog:visible').each(function() {
Ox.UI.elements[$(this).data('oxid')].close();
});
}
// open dialog
if (Ox.contains([
'welcome', 'app', 'preferences', 'users',
'notifications', 'transfers', 'help'
], page)) {
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()
.css({
//overflowX: 'hidden',
overflowX: 'hidden',
//overflowY: 'auto',
})
.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: []
}, function(result) {
if (!identifyData && ui.item != id) {
return;
}
if (result) {
data = result.data;
}

View file

@ -371,7 +371,9 @@ oml.ui.mainMenu = function() {
} else if (id == 'deletelist') {
oml.ui.deleteListDialog().open();
} 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') {
oml.$ui.list.selectAll();
} else if (id == 'selectnone') {
@ -548,11 +550,11 @@ oml.ui.mainMenu = function() {
items: [
{
id: 'import',
title: Ox._('Import Books...')
title: Ox._(oml.user.importing ? 'Importing Books...' : 'Import Books...') // FIXME
},
{
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,
user: data.user
});
// make sure all valid ui settings are present
oml.user.ui = Ox.extend(
Ox.clone(data.config.user.ui, true),
oml.user.ui
);
// make sure no invalid ui settings are present
Object.keys(oml.user.ui).forEach(function(key) {
if (Ox.isUndefined(oml.config.user.ui[key])) {
delete oml.user.ui[key];
}
['preferences', 'ui'].forEach(function(key) {
// make sure all valid settings are present
oml.user[key] = Ox.extend(
Ox.clone(data.config.user[key], true),
oml.user[key]
);
// make sure no invalid settings are present
Object.keys(oml.user[key]).forEach(function(key_) {
if (Ox.isUndefined(oml.config.user[key][key_])) {
delete oml.user[key][key_];
}
});
});
// TODO: make sure listView, listSort and itemView are valid
Ox.extend(oml.config, {

View file

@ -25,7 +25,7 @@ oml.ui.preferencesDialog = function() {
{
id: 'libraryPath',
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.'
},
{
@ -366,7 +366,7 @@ oml.ui.preferencesDialog = function() {
? Ox.Input({
height: 328,
type: 'textarea',
value: item.value,
value: oml.user.preferences[item.id] || item.value,
width: 400
})
: Ox.isBoolean(item.value)
@ -379,7 +379,7 @@ oml.ui.preferencesDialog = function() {
label: Ox._(item.title),
labelWidth: 128,
placeholder: item.placeholder || '',
value: item.value || '',
value: oml.user.preferences[item.id] || item.value || '',
width: 384 - !!item.unit * 48
})

View file

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

View file

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

View file

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