diff --git a/ctl b/ctl index ec1b70b..c0ccd8e 100755 --- a/ctl +++ b/ctl @@ -85,6 +85,7 @@ if [ "$1" == "update" ]; then git pull $0 db upgrade $0 setup + $0 update_static > /dev/null exit fi diff --git a/oml/changelog.py b/oml/changelog.py index eecaba0..7e31cff 100644 --- a/oml/changelog.py +++ b/oml/changelog.py @@ -84,7 +84,7 @@ class Changelog(db.Model): c.data = data c.sig = sig action, args = json.loads(data) - print 'apply change', action + print 'apply change', action, args if getattr(c, 'action_' + action)(user, timestamp, *args): print 'change applied' db.session.add(c) @@ -166,7 +166,8 @@ class Changelog(db.Model): i = Item.get(itemid) if not i or i.timestamp > timestamp: return True - i.users.remove(user) + if user in i.users: + i.users.remove(user) if i.users: i.update() else: diff --git a/oml/commands.py b/oml/commands.py index a9285a7..d496cff 100644 --- a/oml/commands.py +++ b/oml/commands.py @@ -32,6 +32,8 @@ class UpdateStatic(Command): oxjs = os.path.join(settings.static_path, 'oxjs') if not os.path.exists(oxjs): r('git', 'clone', 'https://git.0x2620.org/oxjs.git', oxjs) + elif os.path.exists(os.path.join(oxjs, '.git')): + os.system('cd "%s" && git pull' % oxjs) r('python2', os.path.join(oxjs, 'tools', 'build', 'build.py')) r('python2', os.path.join(settings.static_path, 'py', 'build.py')) diff --git a/oml/item/api.py b/oml/item/api.py index b51d6ad..83fbfaf 100644 --- a/oml/item/api.py +++ b/oml/item/api.py @@ -108,6 +108,15 @@ def edit(request): return response actions.register(edit, cache=False) +@returns_json +def remove(request): + data = json.loads(request.form['data']) if 'data' in request.form else {} + print 'remove files', data['ids'] + if 'ids' in data and data['ids']: + for i in models.Item.query.filter(models.Item.id.in_(data['ids'])): + i.remove_file() + return {} +actions.register(remove, cache=False) @returns_json def findMetadata(request): diff --git a/oml/item/models.py b/oml/item/models.py index 5118364..0b53b12 100644 --- a/oml/item/models.py +++ b/oml/item/models.py @@ -9,6 +9,7 @@ import json import hashlib from datetime import datetime from StringIO import StringIO +import shutil import Image import ox @@ -170,9 +171,7 @@ class Item(db.Model): def get_path(self): f = self.files.first() - prefs = settings.preferences - prefix = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') - return os.path.join(prefix, f.path) if f else None + return f.fullpath() if f else None def update_sort(self): for key in config['itemKeys']: @@ -366,6 +365,22 @@ class Item(db.Model): self.update() return False + def remove_file(self): + for f in self.files.all(): + path = f.fullpath() + print path + if os.path.exists(path): + os.unlink(path) + db.session.delete(f) + user = state.user() + self.users.remove(user) + db.session.commit() + if not self.users: + db.session.delete(self) + else: + self.update() + Changelog.record(user, 'removeitem', self.id) + for key in config['itemKeys']: if key.get('sort'): sort_type = key.get('sortType', key['type']) @@ -445,3 +460,49 @@ class File(db.Model): self.sha1 = sha1 self.created = datetime.now() self.modified = datetime.now() + + def fullpath(self): + prefs = settings.preferences + prefix = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') + return os.path.join(prefix, self.path) + + def move(self): + prefs = settings.preferences + prefix = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') + j = self.item.json() + + current_path = self.fullpath() + author = '; '.join([ox.canonical_name(a) for a in j.get('author', [])]) + if not author: + author = 'Unknown Author' + title = j.get('title', 'Untitled') + extension = j['extension'] + if len(title) > 100: + title = title[:100] + if author.endswith('.'): + author = author[:-1] + '_' + if author.startswith('.'): + author = '_' + author[1:] + filename = '%s.%s' % (title, extension) + print self.sha1, author, filename + new_path = os.path.join(author[0].upper(), author, filename) + if self.path == new_path: + return + h = '' + while os.path.exists(os.path.join(prefix, new_path)): + h = self.sha1[:len(h)+1] + filename = '%s.%s.%s' % (title, h, extension) + new_path = os.path.join(author[0].upper(), author, filename) + if current_path == os.path.join(prefix, new_path): + break + if self.path != new_path: + path = os.path.join(prefix, new_path) + ox.makedirs(os.path.dirname(path)) + shutil.move(current_path, path) + self.path = new_path + self.save() + print 'move', current_path, new_path + + def save(self): + db.session.add(self) + db.session.commit() diff --git a/oml/item/scan.py b/oml/item/scan.py index 094ba0a..7f20052 100644 --- a/oml/item/scan.py +++ b/oml/item/scan.py @@ -25,21 +25,14 @@ extensions = ['epub', 'pdf', 'txt'] def remove_missing(): dirty = False with app.app_context(): - user = User.get_or_create(settings.USER_ID) prefs = settings.preferences prefix = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') for f in File.query: - if not os.path.exists(f.item.get_path()): + path = f.item.get_path() + if not os.path.exists(path): dirty = True - print 'file gone', f, f.item.get_path() - f.item.users.remove(user) - if not f.item.users: - print 'last user, remove' - db.session.delete(f.item) - else: - f.item.update_lists() - Changelog.record(user, 'removeitem', f.item.id) - db.session.delete(f) + print 'file gone', f, path + f.item.remove_file() if dirty: db.session.commit() @@ -171,6 +164,7 @@ def run_import(options=None): item.meta['mainid']: item.meta[item.meta['mainid']] }) item.scrape() + file.move() if listname: listitems.append(item.id) added += 1 diff --git a/oml/node/api.py b/oml/node/api.py index 47cdd39..cd160bd 100644 --- a/oml/node/api.py +++ b/oml/node/api.py @@ -58,6 +58,7 @@ def api_requestPeering(app, user_id, username, message): def api_acceptPeering(app, user_id, username, message): user = User.get(user_id) + print 'incoming acceptPeering event: pending:', user.pending if user and user.pending == 'sent': if not user.info: user.info = {} diff --git a/oml/nodes.py b/oml/nodes.py index 282edea..a51fd44 100644 --- a/oml/nodes.py +++ b/oml/nodes.py @@ -187,7 +187,9 @@ class Node(object): return True def acceptPeering(self, message): + print 'run acceptPeering', message r = self.request('acceptPeering', settings.preferences['username'], message) + print 'result', r p = self.user p.update_peering(True) self.go_online() diff --git a/oml/user/api.py b/oml/user/api.py index ae54b5a..bb9820d 100644 --- a/oml/user/api.py +++ b/oml/user/api.py @@ -192,6 +192,7 @@ def acceptPeering(request): if len(data.get('id', '')) != 43: print 'invalid user id' return {} + print 'acceptPeering...', data p = models.User.get_or_create(data['id']) state.nodes.queue('add', p.id) state.nodes.queue(p.id, 'acceptPeering', data.get('message', '')) diff --git a/oml/user/models.py b/oml/user/models.py index 5fb5019..a0a2f43 100644 --- a/oml/user/models.py +++ b/oml/user/models.py @@ -68,17 +68,23 @@ class User(db.Model): was_peering = self.peered if peered: self.pending = '' - self.peered = True if username: self.info['username'] = username self.set_nickname(self.info.get('username', 'anonymous')) + # FIXME: need to set peered to False to not trigger changelog event + # before other side receives acceptPeering request + self.peered = False + self.save() if not was_peering: Changelog.record(state.user(), 'addpeer', self.id, self.nickname) + self.peered = True + self.save() else: self.pending = '' self.peered = False self.nickname = None + self.save() List.query.filter_by(user_id=self.id).delete() for i in self.items: i.users.remove(self) @@ -167,7 +173,8 @@ class List(db.Model): for item_id in items: i = Item.get(item_id) self.items.append(i) - i.queue_download() + if self.user_id == settings.USER_ID: + i.queue_download() i.update() db.session.add(self) db.session.commit() diff --git a/static/js/appDialog.js b/static/js/appDialog.js index 08488e4..c472124 100644 --- a/static/js/appDialog.js +++ b/static/js/appDialog.js @@ -94,12 +94,12 @@ oml.ui.appDialog = function() { }, 'oml_part.app': function() { if (ui.page == 'app') { - that.update(); + that.updateElement(); } } }); - that.update = function(section) { + that.updateElement = function(section) { $panel.selectTab(section); }; diff --git a/static/js/deleteItemsDialog.js b/static/js/deleteItemsDialog.js new file mode 100644 index 0000000..72e451b --- /dev/null +++ b/static/js/deleteItemsDialog.js @@ -0,0 +1,37 @@ +'use strict'; + +oml.ui.deleteItemsDialog = function() { + + var ui = oml.user.ui, + + items = ui.listSelection, + itemsName = Ox._(items.length == 1 ? 'Item' : 'Items'), + theseItemsName = items.length == 1 + ? Ox._('this item') + : Ox._('these {0} items', [Ox.formatNumber(items.length)]), + + that = oml.ui.confirmDialog({ + buttons: [ + Ox.Button({ + title: Ox._('No, Keep {0}', [itemsName]) + }), + Ox.Button({ + title: Ox._('Yes, Delete {0}', [itemsName]) + }) + ], + content: Ox._('Are you sure that you want to permanently delete {0}?', [theseItemsName]), + title: Ox._('Delete {0}', [itemsName]) + }, function() { + oml.api.remove({ + ids: items + }, function() { + oml.UI.set({listSelection: []}); + Ox.Request.clearCache('find'); + oml.$ui.folders.updateElement(); + oml.$ui.list.updateElement(); + }); + }); + + return that; + +}; \ No newline at end of file diff --git a/static/js/errorDialog.js b/static/js/errorDialog.js index e02e94f..20eac27 100644 --- a/static/js/errorDialog.js +++ b/static/js/errorDialog.js @@ -54,7 +54,7 @@ oml.ui.errorDialog = function() { return that; }; - that.update = function(data) { + that.updateElement = function(data) { // 0 (timeout) or 500 (error) var error = data.status.code == 0 ? 'a timeout' : 'an error', title = data.status.code == 0 ? 'Timeout' : 'Error'; diff --git a/static/js/filtersOuterPanel.js b/static/js/filtersOuterPanel.js index 20876dc..8e14eaa 100644 --- a/static/js/filtersOuterPanel.js +++ b/static/js/filtersOuterPanel.js @@ -88,7 +88,7 @@ oml.ui.filtersOuterPanel = function() { oml.updateFilterMenus(); - that.update = function() { + that.updateElement = function() { var filterSizes = oml.getFilterSizes(); that.size(0, filterSizes[0]) .size(2, filterSizes[4]); diff --git a/static/js/folderPlaceholder.js b/static/js/folderPlaceholder.js index 6921fe9..797171a 100644 --- a/static/js/folderPlaceholder.js +++ b/static/js/folderPlaceholder.js @@ -11,10 +11,10 @@ oml.ui.folderPlaceholder = function(text) { padding: '1px 4px', }); - that.updateText = function(text) { + that.updateElement = function(text) { return that.html(text); }; - return that.updateText(text); + return that.updateElement(text); }; \ No newline at end of file diff --git a/static/js/folders.js b/static/js/folders.js index 3f4526a..f50753c 100644 --- a/static/js/folders.js +++ b/static/js/folders.js @@ -4,9 +4,9 @@ oml.ui.folders = function() { var ui = oml.user.ui, - userIndex = {}, + userIndex, - $lists = [], + $lists, that = Ox.Element() .css({ @@ -17,219 +17,6 @@ oml.ui.folders = function() { oml_find: selectList }); - $lists.push( - oml.$ui.librariesList = oml.ui.folderList({ - items: [ - { - id: '', - name: Ox._('All Libraries'), - type: 'libraries', - items: -1 - } - ] - }) - .bindEvent({ - load: function() { - oml.api.find({query: getFind()}, function(result) { - oml.$ui.librariesList.value('', 'items', result.data.items); - }); - }, - select: function() { - oml.UI.set({find: getFind('')}); - oml.$ui.librariesList.options({selected: ['']}); - }, - selectnext: function() { - oml.UI.set(Ox.extend( - {find: getFind(':')}, - 'showFolder.' + oml.user.preferences.username, - true - )); - }, - }) - .css({height: '16px'}) - .appendTo(that) - ); - oml.$ui.librariesList.$body.css({height: '16px'}); // FIXME! - - oml.$ui.folder = []; - oml.$ui.libraryList = []; - oml.$ui.folderList = []; - - oml.getUsersAndLists(function(users, lists) { - - Ox.print('GOT USERS AND LISTS', users, lists); - - users.forEach(function(user, index) { - - var $content, - items = lists.filter(function(list) { - return list.user == user.nickname - && list.type != 'library'; - }), - libraryId = (!index ? '' : user.nickname) + ':' - - userIndex[user.nickname] = index; - - oml.$ui.folder[index] = Ox.CollapsePanel({ - collapsed: false, - extras: [ - oml.ui.statusIcon( - !oml.user.online && index ? 'unknown' - : user.online ? 'connected' - : 'disconnected' - ), - {}, - Ox.Button({ - style: 'symbol', - title: 'info', - tooltip: Ox._(!index ? 'Preferences' : 'Profile'), - type: 'image' - }) - .bindEvent({ - click: function() { - if (!index) { - oml.UI.set({ - page: 'preferences', - 'part.preferences': 'account' - }); - } else { - oml.UI.set({page: 'users'}) - } - } - }) - ], - title: Ox.encodeHTMLEntities(user.nickname) - }) - .css({ - width: ui.sidebarSize - }) - .bindEvent({ - toggle: function(data) { - oml.UI.set('showFolder.' + user.nickname, !data.collapsed); - } - }) - .bindEvent( - 'oml_showfolder.' + user.nickname.toLowerCase(), - function(data) { - oml.$ui.folder[index].options({collapsed: !data.value}); - } - ) - .appendTo(that); - - $content = oml.$ui.folder[index].$content - .css({ - height: (1 + items.length) * 16 + 'px' - }); - - $lists.push( - oml.$ui.libraryList[index] = oml.ui.folderList({ - items: [ - { - id: libraryId, - name: Ox._('Library'), - type: 'library', - items: -1 - } - ] - }) - .bindEvent({ - add: function() { - !index && oml.addList(); - }, - load: function() { - oml.api.find({ - query: getFind(libraryId) - }, function(result) { - oml.$ui.libraryList[index].value( - libraryId, 'items', result.data.items - ); - }); - }, - select: function(data) { - oml.UI.set({find: getFind(data.ids[0])}); - }, - selectnext: function() { - oml.UI.set({find: getFind(lists[user.id][0].id)}); - }, - selectprevious: function() { - var userId = !index ? null : users[index - 1].id, - set = { - find: getFind( - !index - ? '' - : Ox.last(lists[userId]).id - ) - }; - if (userId) { - Ox.extend(set, 'showFolder.' + userId, true); - } - oml.UI.set(set); - } - }) - .appendTo($content) - ); - - $lists.push( - oml.$ui.folderList[index] = oml.ui.folderList({ - draggable: !!index, - items: items, - sortable: !index - }) - .bindEvent({ - add: function() { - !index && oml.addList(); - }, - 'delete': function() { - !index && oml.ui.deleteListDialog().open(); - }, - key_control_d: function() { - oml.addList(ui._list); - }, - load: function() { - // ... - }, - move: function(data) { - lists[user.id] = data.ids.map(function(listId) { - return Ox.getObjectById(lists[user.id], listId); - }); - oml.api.sortLists({ - ids: data.ids, - user: user.id - }, function(result) { - // ... - }); - }, - open: function() { - !index && oml.ui.listDialog().open(); - }, - select: function(data) { - oml.UI.set({find: getFind(data.ids[0])}); - }, - selectnext: function() { - if (index < users.length - 1) { - oml.UI.set(Ox.extend( - {find: getFind(users[index + 1].nickname + ':')}, - 'showFolder.' + users[index + 1].nickname, - true - )); - } - }, - selectprevious: function() { - oml.UI.set({find: getFind(libraryId)}); - } - }) - .css({height: items.length * 16 + 'px'}) - .appendTo($content) - ); - - oml.$ui.folderList[index].$body.css({top: '16px'}); - - }); - - selectList(); - - }); - function getFind(list) { return { conditions: list ? [{ @@ -257,6 +44,230 @@ oml.ui.folders = function() { }); } - return that; + that.updateElement = function() { + + that.empty(); + + $lists = []; + + $lists.push( + oml.$ui.librariesList = oml.ui.folderList({ + items: [ + { + id: '', + name: Ox._('All Libraries'), + type: 'libraries', + items: -1 + } + ] + }) + .bindEvent({ + load: function() { + oml.api.find({query: getFind()}, function(result) { + oml.$ui.librariesList.value('', 'items', result.data.items); + }); + }, + select: function() { + oml.UI.set({find: getFind('')}); + oml.$ui.librariesList.options({selected: ['']}); + }, + selectnext: function() { + oml.UI.set(Ox.extend( + {find: getFind(':')}, + 'showFolder.' + oml.user.preferences.username, + true + )); + }, + }) + .css({height: '16px'}) + .appendTo(that) + ); + oml.$ui.librariesList.$body.css({height: '16px'}); // FIXME! + + oml.$ui.folder = []; + oml.$ui.libraryList = []; + oml.$ui.folderList = []; + + oml.getUsersAndLists(function(users, lists) { + + Ox.print('GOT USERS AND LISTS', users, lists); + userIndex = {}; + + users.forEach(function(user, index) { + + var $content, + items = lists.filter(function(list) { + return list.user == user.nickname + && list.type != 'library'; + }), + libraryId = (!index ? '' : user.nickname) + ':' + + userIndex[user.nickname] = index; + + oml.$ui.folder[index] = Ox.CollapsePanel({ + collapsed: false, + extras: [ + oml.ui.statusIcon( + !oml.user.online && index ? 'unknown' + : user.online ? 'connected' + : 'disconnected' + ), + {}, + Ox.Button({ + style: 'symbol', + title: 'info', + tooltip: Ox._(!index ? 'Preferences' : 'Profile'), + type: 'image' + }) + .bindEvent({ + click: function() { + if (!index) { + oml.UI.set({ + page: 'preferences', + 'part.preferences': 'account' + }); + } else { + oml.UI.set({page: 'users'}) + } + } + }) + ], + title: Ox.encodeHTMLEntities(user.nickname) + }) + .css({ + width: ui.sidebarSize + }) + .bindEvent({ + toggle: function(data) { + oml.UI.set('showFolder.' + user.nickname, !data.collapsed); + } + }) + .bindEvent( + 'oml_showfolder.' + user.nickname.toLowerCase(), + function(data) { + oml.$ui.folder[index].options({collapsed: !data.value}); + } + ) + .appendTo(that); + + $content = oml.$ui.folder[index].$content + .css({ + height: (1 + items.length) * 16 + 'px' + }); + + $lists.push( + oml.$ui.libraryList[index] = oml.ui.folderList({ + items: [ + { + id: libraryId, + name: Ox._('Library'), + type: 'library', + items: -1 + } + ] + }) + .bindEvent({ + add: function() { + !index && oml.addList(); + }, + load: function() { + oml.api.find({ + query: getFind(libraryId) + }, function(result) { + oml.$ui.libraryList[index].value( + libraryId, 'items', result.data.items + ); + }); + }, + select: function(data) { + oml.UI.set({find: getFind(data.ids[0])}); + }, + selectnext: function() { + oml.UI.set({find: getFind(items[0].id)}); + }, + selectprevious: function() { + var userId = !index ? null : users[index - 1].id, + set = { + find: getFind( + !index + ? '' + : Ox.last(lists[userId]).id + ) + }; + if (userId) { + Ox.extend(set, 'showFolder.' + userId, true); + } + oml.UI.set(set); + } + }) + .appendTo($content) + ); + + $lists.push( + oml.$ui.folderList[index] = oml.ui.folderList({ + draggable: !!index, + items: items, + sortable: !index + }) + .bindEvent({ + add: function() { + !index && oml.addList(); + }, + 'delete': function() { + !index && oml.ui.deleteListDialog().open(); + }, + key_control_d: function() { + oml.addList(ui._list); + }, + load: function() { + // ... + }, + move: function(data) { + lists[user.id] = data.ids.map(function(listId) { + return Ox.getObjectById(items, listId); + }); + oml.api.sortLists({ + ids: data.ids, + user: user.id + }, function(result) { + // ... + }); + }, + open: function() { + !index && oml.ui.listDialog().open(); + }, + select: function(data) { + oml.UI.set({find: getFind(data.ids[0])}); + }, + selectnext: function() { + if (index < users.length - 1) { + oml.UI.set(Ox.extend( + {find: getFind(users[index + 1].nickname + ':')}, + 'showFolder.' + users[index + 1].nickname, + true + )); + } + }, + selectprevious: function() { + oml.UI.set({find: getFind(libraryId)}); + } + }) + .css({height: items.length * 16 + 'px'}) + .appendTo($content) + ); + + oml.$ui.folderList[index].$body.css({top: '16px'}); + + }); + + selectList(); + + }); + + return that; + + }; + + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/fullscreenButton.js b/static/js/fullscreenButton.js index e378030..5ab741e 100644 --- a/static/js/fullscreenButton.js +++ b/static/js/fullscreenButton.js @@ -19,16 +19,16 @@ oml.ui.fullscreenButton = function() { Ox.Fullscreen.enter(oml.$ui.viewer.find('iframe')[0]); }, oml_itemview: function() { - that.update(); + that.updateElement(); } }); - that.update = function() { + that.updateElement = function() { return that.options({ disabled: ui.itemView != 'book' }); }; - return that.update(); + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/identifyDialog.js b/static/js/identifyDialog.js index 19d8532..57af3c4 100644 --- a/static/js/identifyDialog.js +++ b/static/js/identifyDialog.js @@ -135,7 +135,7 @@ oml.ui.identifyDialog = function(data) { Ox.Request.clearCache('find'); oml.$ui.browser.reloadList(true); Ox.Request.clearCache(data.id); - oml.$ui.infoView.update(result.data); + oml.$ui.infoView.updateElement(result.data); }); } }) diff --git a/static/js/info.js b/static/js/info.js index 92896e7..4eb10f9 100644 --- a/static/js/info.js +++ b/static/js/info.js @@ -6,21 +6,21 @@ oml.ui.info = function() { that = Ox.Element() .addClass('OxTextPage') - .css({ - padding: '0 16px', + .css({ + padding: '0 16px', textAlign: 'center', - overflowY: 'auto' - }) - .bindEvent({ + overflowY: 'auto' + }) + .bindEvent({ oml_item: function() { - that.update(); + that.updateElement(); }, - oml_listselection: function() { - that.update(); - } - }); + oml_listselection: function() { + that.updateElement(); + } + }); - that.update = function() { + that.updateElement = function() { var id = ui.item || ui.listSelection[0]; if (id) { oml.api.get({ @@ -64,6 +64,6 @@ oml.ui.info = function() { return that; }; - return that.update(); + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/infoView.js b/static/js/infoView.js index 869f7cb..073e58b 100644 --- a/static/js/infoView.js +++ b/static/js/infoView.js @@ -10,12 +10,12 @@ oml.ui.infoView = function(identifyData) { .bindEvent({ oml_item: function() { if (ui.item) { - that.update(ui.item); + that.updateElement(ui.item); } }, oml_listselection: function(data) { if (data.value && data.value.length) { - that.update(data.value[0]); + that.updateElement(data.value[0]); } } }), @@ -141,7 +141,7 @@ oml.ui.infoView = function(identifyData) { .bindEvent({ click: function() { data.mediastate = 'transferring'; - that.update(data, $data); + that.updateElement(data, $data); oml.api.download({id: ui.item}, function(result) { // ... }); @@ -158,7 +158,7 @@ oml.ui.infoView = function(identifyData) { .bindEvent({ click: function(data) { data.mediastate = 'transferring'; - that.update(data, $data); + that.updateElement(data, $data); oml.api.download(Ox.extend({ id: ui.item, }, data.id == ':' ? {} : { @@ -192,9 +192,9 @@ oml.ui.infoView = function(identifyData) { .bindEvent({ click: function() { data.mediastate = 'unavailable'; - that.update(data, $data); + that.updateElement(data, $data); oml.api.cancelDownload({id: ui.item}, function() { - that.update(ui.item, $data); + that.updateElement(ui.item, $data); }); } }) @@ -232,7 +232,7 @@ oml.ui.infoView = function(identifyData) { }).show(); } - that.update = function(idOrData, $elements) { + that.updateElement = function(idOrData, $elements) { var data = Ox.isObject(idOrData) ? idOrData : null, id = data ? null : idOrData, @@ -509,7 +509,7 @@ oml.ui.infoView = function(identifyData) { oml.api.edit(edit, function(result) { Ox.Request.clearCache('find'); oml.$ui.browser.reloadList(); - that.update(result.data, $data); + that.updateElement(result.data, $data); }); } } @@ -519,16 +519,16 @@ oml.ui.infoView = function(identifyData) { }; if (!identifyData) { - ui.item && that.update(ui.item); + ui.item && that.updateElement(ui.item); } else { - that.update(identifyData, [$cover, $info]); + that.updateElement(identifyData, [$cover, $info]); } oml.bindEvent({ transfer: function(data) { if (data.id == ui.item && data.progress == 1) { Ox.Request.clearCache(); // FIXME: too much - that.update(ui.item, [$info, $data]); + that.updateElement(ui.item, [$info, $data]); } } }); diff --git a/static/js/itemViewButtons.js b/static/js/itemViewButtons.js index fb5e916..9765195 100644 --- a/static/js/itemViewButtons.js +++ b/static/js/itemViewButtons.js @@ -30,17 +30,17 @@ oml.ui.itemViewButtons = function() { }, oml_item: function() { if (ui.item) { - that.update(); + that.updateElement(); } else { that.disableButton('book'); } }, oml_itemview: function(data) { - that.update(); + that.updateElement(); } }); - that.update = function() { + that.updateElement = function() { var item = ui.item; that.options({ disabled: ui.itemView != 'book', @@ -68,6 +68,6 @@ oml.ui.itemViewButtons = function() { } }); - return that.update(); + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/list.js b/static/js/list.js index dec2c98..b817b96 100644 --- a/static/js/list.js +++ b/static/js/list.js @@ -11,9 +11,50 @@ oml.ui.list = function() { oml.$ui.previewDialog.close(); delete oml.$ui.previewDialog; }, + copy: function(data) { + oml.clipboard.copy(data.ids, 'item'); + }, + copyadd: function(data) { + oml.clipboard.copy(data.ids, 'item'); + }, + cut: function(data) { + var listData = oml.getListData(); + if (listData.editable && listData.type == 'static') { + oml.clipboard.copy(data.ids, 'item'); + oml.doHistory('cut', data.ids, ui._list, function() { + oml.UI.set({listSelection: []}); + oml.reloadList(); + }); + } + }, + cutadd: function(data) { + var listData = oml.getListData(); + if (listData.editable && listData.type == 'static') { + oml.clipboard.add(data.ids, 'item'); + oml.doHistory('cut', data.ids, ui._list, function() { + oml.UI.set({listSelection: []}); + oml.reloadList(); + }); + } + }, + 'delete': function() { + var listData = oml.getListData(); + if (listData.editable && listData.type == 'static') { + oml.doHistory('delete', data.ids, ui._list, function() { + oml.UI.set({listSelection: []}); + oml.reloadList(); + }); + } + }, init: function(data) { oml.$ui.statusbar.set('total', data); }, + key_control_delete: function() { + var listData = oml.getListData(); + if (listData.own) { + oml.ui.deleteItemsDialog().open(); + } + }, open: function(data) { oml.UI.set({ item: data.ids[0], @@ -32,7 +73,7 @@ oml.ui.list = function() { } }); } else { - oml.$ui.previewDialog.update(); + oml.$ui.previewDialog.updateElement(); } }, resize: function(data) { @@ -65,6 +106,10 @@ oml.ui.list = function() { oml.enableDragAndDrop(that); + that.updateElement = function() { + that.reloadList(true); + }; + return that; }; \ No newline at end of file diff --git a/static/js/loadingIcon.js b/static/js/loadingIcon.js index 898fbb5..f5b7952 100644 --- a/static/js/loadingIcon.js +++ b/static/js/loadingIcon.js @@ -40,7 +40,7 @@ oml.ui.loadingIcon = function() { } }; - that.update = function(requests) { + that.updateElement = function(requests) { that[requests ? 'start' : 'stop'](); }; diff --git a/static/js/mainMenu.js b/static/js/mainMenu.js index f5b04c1..02d82b2 100644 --- a/static/js/mainMenu.js +++ b/static/js/mainMenu.js @@ -319,8 +319,30 @@ oml.ui.mainMenu = function() { oml.UI.set({showFileInfo: value}); } else if (id == 'fileinfo') { oml.UI.set({fileInfo: value}); + } else if (id == 'sort') { + oml.UI.set({ + listSort: [{ + key: value, + operator: oml.getSortOperator(value) + }] + }); + } else if (id == 'order') { + oml.UI.set({ + listSort: [{ + key: ui.listSort[0].key, + operator: value == 'ascending' ? '+' : '-' + }] + }); + } else if (id == 'find') { + if (value) { + oml.$ui.findSelect.value(value); + if (ui._findState.key == 'advanced') { + // fixme: autocomplete function doesn't get updated + pandora.$ui.findInput.options({placeholder: ''}); + } + } } else { - Ox.print('MAIN MENU DOES NOT YET HANDLE', id); + Ox.print('MAIN MENU DOES NOT YET HANDLE', id, data); } }, click: function(data) { @@ -441,6 +463,9 @@ oml.ui.mainMenu = function() { that.options('menus')[0].element.trigger('click'); } }, + key_control_shift_f: function() { + Ox.print('FIXME: NOT IMPLEMENTED') + }, key_control_shift_w: function() { if (!oml.hasDialogOrScreen()) { oml.UI.set({ @@ -628,7 +653,7 @@ oml.ui.mainMenu = function() { id: 'deletefromlibrary', title: Ox._('Delete {0} from Library...', [selectionItemName]), disabled: !canDelete, - keyboard: 'shift delete' + keyboard: 'control delete' }, {}, { @@ -716,19 +741,19 @@ oml.ui.mainMenu = function() { id: 'editlist', title: Ox._('Edit List...'), keyboard: 'return', - disabled: !isOwnList + disabled: !isList || !isOwnList }, { id: 'deletelist', title: Ox._('Delete List...'), keyboard: 'delete', - disabled: !isOwnList + disabled: !isList || !isOwnList } ]) }; } - that.update = function(menu) { + that.updateElement = function(menu) { ( menu ? Ox.makeArray(menu) : ['listMenu', 'editMenu'] ).forEach(function(menu) { diff --git a/static/js/oml.js b/static/js/oml.js index 0e924a6..bb96248 100644 --- a/static/js/oml.js +++ b/static/js/oml.js @@ -91,13 +91,13 @@ oml.clipboard = Ox.Clipboard(); oml.history = Ox.History(); oml.$ui.appPanel = oml.ui.appPanel().appendTo(Ox.$body); - oml.$ui.loadingIcon.update(Ox.Request.requests()); + oml.$ui.loadingIcon.updateElement(Ox.Request.requests()); Ox.Request.bindEvent({ error: function(data) { - oml.$ui.errorDialog = oml.ui.errorDialog().update(data).open(); + oml.$ui.errorDialog = oml.ui.errorDialog().updateElement(data).open(); }, request: function(data) { - oml.$ui.loadingIcon.update(data.requests); + oml.$ui.loadingIcon.updateElement(data.requests); } }); if (oml.user.preferences.extensions) { diff --git a/static/js/openButton.js b/static/js/openButton.js index 8c5186e..b665c2b 100644 --- a/static/js/openButton.js +++ b/static/js/openButton.js @@ -23,10 +23,10 @@ oml.ui.openButton = function() { } }); - that.update = function() { + that.updateElement = function() { return that.options({disabled: ui.listSelection.length == 0}); }; - return that.update(); + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/preferencesDialog.js b/static/js/preferencesDialog.js index 14e0ca5..22f8724 100644 --- a/static/js/preferencesDialog.js +++ b/static/js/preferencesDialog.js @@ -297,7 +297,7 @@ oml.ui.preferencesDialog = function() { }, 'oml_part.preferences': function() { if (ui.page == 'preferences') { - that.update(); + that.updateElement(); } } }); @@ -308,7 +308,7 @@ oml.ui.preferencesDialog = function() { $helpElement.show(); } - that.update = function() { + that.updateElement = function() { var $form, $formTitle, @@ -439,6 +439,6 @@ oml.ui.preferencesDialog = function() { }; - return that.update(); + return that.updateElement(); }; diff --git a/static/js/previewButton.js b/static/js/previewButton.js index 1be01b5..fa1b781 100644 --- a/static/js/previewButton.js +++ b/static/js/previewButton.js @@ -20,15 +20,15 @@ oml.ui.previewButton = function() { oml.$ui.list[data.value ? 'openPreview' : 'closePreview'](); }, oml_listselection: function() { - that.update(); + that.updateElement(); } }); - that.update = function() { + that.updateElement = function() { return that.options({disabled: ui.listSelection.length == 0}); }; - return that.update(); + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/previewDialog.js b/static/js/previewDialog.js index be49e58..7f66d23 100644 --- a/static/js/previewDialog.js +++ b/static/js/previewDialog.js @@ -52,7 +52,7 @@ oml.ui.previewDialog = function() { }; } - that.update = function() { + that.updateElement = function() { oml.api.get({ id: Ox.last($list.options('selected')), keys: ['coverRatio', 'id', 'modified', 'title'] @@ -87,6 +87,6 @@ oml.ui.previewDialog = function() { return that; }; - return that.update(); + return that.updateElement(); }; diff --git a/static/js/rightPanel.js b/static/js/rightPanel.js index 648d027..5a1b27c 100644 --- a/static/js/rightPanel.js +++ b/static/js/rightPanel.js @@ -22,7 +22,7 @@ oml.ui.rightPanel = function() { .bindEvent({ resize: function(data) { that.options({size: data.size}); - oml.$ui.filtersOuterPanel.update(); + oml.$ui.filtersOuterPanel.updateElement(); oml.$ui.itemViewPanel.options({size: data.size}); }, oml_item: function(data) { diff --git a/static/js/sortElement.js b/static/js/sortElement.js index dd66631..68c9495 100644 --- a/static/js/sortElement.js +++ b/static/js/sortElement.js @@ -18,10 +18,7 @@ oml.ui.sortElement = function() { change: function(data) { var key = data.value; oml.UI.set({ - listSort: [{ - key: key, - operator: oml.getSortOperator(key) - }] + listSort: [{key: key, operator: oml.getSortOperator(key)}] }); } }), @@ -54,7 +51,7 @@ oml.ui.sortElement = function() { }) .bindEvent({ oml_listsort: function() { - that.update(); + that.updateElement(); } }); @@ -66,7 +63,7 @@ oml.ui.sortElement = function() { return Ox._(ui.listSort[0].operator == '+' ? 'Ascending' : 'Descending'); } - that.update = function() { + that.updateElement = function() { $sortSelect.value(ui.listSort[0].key); $orderButton.options({ title: getButtonTitle(), @@ -75,6 +72,6 @@ oml.ui.sortElement = function() { return that; }; - return that.update(); + return that.updateElement(); }; \ No newline at end of file diff --git a/static/js/usersDialog.js b/static/js/usersDialog.js index 2a78d69..fe4c897 100644 --- a/static/js/usersDialog.js +++ b/static/js/usersDialog.js @@ -519,7 +519,7 @@ oml.ui.usersDialog = function() { } function updateUsers(callback) { - + Ox.Request.clearCache('getUsers'); oml.api.getUsers(function(result) { users = result.data.users; @@ -582,7 +582,7 @@ oml.ui.usersDialog = function() { } - that.update = function() { + that.updateElement = function() { that.options({ content: Ox.LoadingScreen().start() @@ -592,6 +592,6 @@ oml.ui.usersDialog = function() { }; - return that.update(); + return that.updateElement(); }; diff --git a/static/js/utils.js b/static/js/utils.js index 0c48390..bcbc0c6 100644 --- a/static/js/utils.js +++ b/static/js/utils.js @@ -283,7 +283,7 @@ oml.enableDragAndDrop = function($list, canMove) { editable: data.editable || ( data.type == 'library' && drag.source.user != username - && data.user == 'username' + && data.user == username ), selected: data.id == ui._list }, data); @@ -773,6 +773,8 @@ oml.getUsersAndLists = function(callback) { nickname: username, online: oml.user.online }]; + Ox.Request.clearCache('getUsers'); + Ox.Request.clearCache('getLists'); oml.api.getUsers(function(result) { users = users.concat( result.data.users.filter(function(user) { @@ -793,13 +795,15 @@ oml.getUsersAndLists = function(callback) { )); }); lists = lists.map(function(list) { + // FIXME: 'editable' is notoriously vague return Ox.extend(list, { editable: list.user == username && list.type == 'static', + own: list.user == username, title: (list.user ? list.user + ': ' : '') + list.name }); }) if (!ui.lists) { - oml.$ui.mainMenu.update(); + oml.$ui.mainMenu.updateElement(); } ui._lists = lists; Ox.print('UI._LISTS', JSON.stringify(ui._lists)); @@ -829,17 +833,19 @@ oml.resizeListFolders = function() { var width = oml.getListFoldersWidth(), columnWidth = width - 58; oml.$ui.librariesList - .resizeColumn('name', columnWidth) - .css({width: width + 'px'}); + .css({width: width + 'px'}) + .resizeColumn('name', columnWidth); Ox.forEach(oml.$ui.folder, function($folder, index) { $folder.css({width: width + 'px'}); + Ox.print('SHOULD BE:', width); oml.$ui.libraryList[index] - .resizeColumn('name', columnWidth) - .css({width: width + 'px'}); + .css({width: width + 'px'}) + .resizeColumn('name', columnWidth); oml.$ui.folderList[index] - .resizeColumn('name', columnWidth) - .css({width: width + 'px'}); + .css({width: width + 'px'}) + .resizeColumn('name', columnWidth); }); + /* oml.$ui.librariesList .$body.find('.OxContent') .css({width: width + 'px'}); @@ -851,6 +857,7 @@ oml.resizeListFolders = function() { .$body.find('.OxContent') .css({width: width + 'px'}); }) + */ }; oml.updateFilterMenus = function() { diff --git a/static/js/viewer.js b/static/js/viewer.js index 7e71ed9..8564666 100644 --- a/static/js/viewer.js +++ b/static/js/viewer.js @@ -7,16 +7,16 @@ oml.ui.viewer = function() { that = Ox.Element() .bindEvent({ oml_item: function(data) { - that.update(); + that.updateElement(); }, oml_itemview: function(data) { - that.update(); + that.updateElement(); } }), $iframe; - that.update = function() { + that.updateElement = function() { if (ui.item && ui.itemView == 'book') { $iframe = $iframe || Ox.Element('