diff --git a/pandora/0xdb.json b/pandora/0xdb.json index 44b99a96..133e5a5b 100644 --- a/pandora/0xdb.json +++ b/pandora/0xdb.json @@ -32,341 +32,378 @@ {"id": "keyword", "title": "Keyword"} ], "itemKeys": [ - { + { "id": "title", "title": "Title", "type": "string", - "find": {"autocomplete": true, "autocompleteSortKey": "votes"}, - "sort": {"removable": false, "type": "title", "width": 180} + "autocomplete": true, + "autocompleteSortKey": "votes", + "columnRequired": true, + "columnWidth": 180, + "find": true, + "sort": "title" }, { "id": "director", "title": "Director", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"removable": false, "type": "person", "width": 180}, - "group": true + "autocomplete": true, + "columnRequired": true, + "columnWidth": 180, + "find": true, + "group": true, + "sort": "person" }, { "id": "country", "title": "Country", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"type": "string", "width": 120}, + "autocomplete": true, + "columnWidth": 120, + "find": true, "group": true }, { "id": "year", "title": "Year", "type": "year", - "find": {"autocomplete": true}, - "sort": {"type": "year", "width": 60}, + "autocomplete": true, + "columnWidth": 60, + "find": true, "group": true }, { "id": "language", "title": "Language", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"type": "string", "width": 120}, + "autocomplete": true, + "columnWidth": 120, + "find": true, "group": true }, { "id": "runtime", "title": "Runtime", "type": "integer", - "sort": {"type": "integer", "width": 60}, + "columnWidth": 60, "format": {"type": "duration", "args": [0, "medium"]} }, { "id": "writer", "title": "Writer", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"type": "person", "width": 180}, - "group": true + "autocomplete": true, + "columnWidth": 180, + "find": true, + "group": true, + "sort": "person" }, { "id": "producer", - "type": ["string"], "title": "Producer", - "find": {"autocomplete": true}, - "sort": {"type": "person", "width": 180}, - "group": true + "type": ["string"], + "autocomplete": true, + "columnWidth": 180, + "find": true, + "group": true, + "sort": "person" }, { "id": "cinematographer", "title": "Cinematographer", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"type": "person", "width": 180}, - "group": true + "autocomplete": true, + "columnWidth": 180, + "find": true, + "group": true, + "sort": "person" }, { "id": "editor", "title": "Editor", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"type": "person", "width": 180}, - "group": true + "autocomplete": true, + "columnWidth": 180, + "find": true, + "group": true, + "sort": "person" }, { "id": "actor", - "title": "Actor", + "title": "Actor", "type": ["string"], - "find": {"autocomplete": true}, - "group": true + "autocomplete": true, + "find": true, + "group": true, + "sort": "person" }, { "id": "numberofactors", "title": "Number of Actors", - "sort": {"type": "integer", "width": 60}, - "value": {"key": "actor", "type": "length"}, - "type": "integer" + "type": "integer", + "columnWidth": 60, + "value": {"key": "actor", "type": "length"} }, { "id": "character", "title": "Character", "type": ["string"], - "find": {"autocomplete": true} + "autocomplete": true, + "find": true, + "sort": "person" }, { "id": "name", - "title": "Name", + "title": "Name", "type": ["string"], - "find": {"autocomplete": true} + "autocomplete": true, + "find": true }, { "id": "genre", - "title": "Genre", + "title": "Genre", "type": ["string"], - "find": {"autocomplete": true}, - "sort": {"type": "string", "width": 120}, + "autocomplete": true, + "columnWidth": 120, + "find": true, "group": true }, { "id": "keyword", - "title": "Keyword", + "title": "Keyword", "type": ["string"], - "find": {"autocomplete": true}, + "autocomplete": true, + "find": true, "group": true }, { "id": "numberofkeywords", - "title": "Number of Keyword", + "title": "Number of Keywords", "type": "integer", - "sort": {"type": "integer", "width": 60}, + "columnWidth": 60, "value": {"key": "keyword", "type": "length"} }, { "id": "summary", "title": "Summary", "type": "text", - "group": false, - "find": {} + "find": true }, { "id": "wordsinsummary", "title": "Words in Summary", - "sort": {"type": "integer", "width": 60}, "type": "integer", + "columnWidth": 60, "value": {"key": "summary", "type": "words"} }, + { + "id": "trivia", + "title": "Trivia", + "type": ["text"] + }, { "id": "wordsintrivia", "title": "Words in Trivia", "type": "integer", - "sort": {"type": "integer", "width": 60}, + "columnWidth": 60, "value": {"key": "trivia", "type": "words"} }, { "id": "releasedate", "title": "Release Date", - "sort": {"type": "date", "width": 120}, "type": "date", + "columnWidth": 120, "format": {"type": "date", "args": ["%a, %b %e, %Y"]} }, { "id": "budget", "title": "Budget", - "sort": {"type": "integer", "width": 90}, "type": "integer", + "columnWidth": 90, "format": {"type": "currency", "args": ["$", 0]} }, { "id": "gross", "title": "Gross", - "sort": {"type": "integer", "width": 90}, "type": "integer", + "columnWidth": 90, "format": {"type": "currency", "args": ["$", 0]} }, { "id": "profit", "title": "Profit", - "sort": {"type": "integer", "width": 90}, "type": "integer", + "columnWidth": 90, "format": {"type": "currency", "args": ["$", 0]} }, { "id": "rating", "title": "Rating", - "sort": {"type": "float", "width": 60}, "type": "float", + "columnWidth": 60, "format": {"type": "percent", "args": [10, 2]} }, { "id": "votes", "title": "Votes", - "sort": {"type": "integer", "width": 60}, "type": "integer", - "format": {"type": "percent", "args": [403824, 2]} + "columnWidth": 60, + "format": {"type": "percent", "args": ["auto", 2]} }, { "id": "id", "title": "ID", - "sort": {"type": "string", "width": 90}, - "type": "string" + "type": "string", + "columnWidth": 90 }, { - "id": "dialog", - "title": "Dialog", - "type": "text", - "group": false, - "find": {} - }, - { - "id": "aspectratio", - "title": "Aspect Ratio", - "sort": {"type": "float", "width": 90}, - "type": "float" + "id": "subtitles", + "title": "Subtitles", + "type": "layer", + "find": true }, { "id": "duration", "title": "Duration", - "sort": {"type": "float", "width": 90}, - "type": "float" - }, - { - "id": "color", - "title": "Color", - "sort": {"type": "float", "width": 90}, - "type": "float" - }, - { - "id": "saturation", - "title": "Saturation", - "sort": {"type": "float", "width": 60}, - "type": "float" - }, - { - "id": "brightness", - "title": "Brightness", - "sort": {"type": "float", "width": 60}, - "type": "float" - }, - { - "id": "volume", - "title": "Volume", - "sort": {"type": "float", "width": 60}, - "type": "float" - }, - { - "id": "clips", - "title": "Clips", - "sort": {"type": "integer", "width": 60}, - "type": "integer" - }, - { - "id": "cuts", - "title": "Cuts", - "sort": {"type": "integer", "width": 60}, - "type": "integer" - }, - { - "id": "cutsperminute", - "title": "Cuts per Minute", - "sort": {"type": "float", "width": 60}, - "type": "float" - }, - { - "id": "words", - "title": "Words", - "sort": {"type": "integer", "width": 60}, - "type": "integer" - }, - { - "id": "wordsperminute", - "title": "Words per Minute", - "sort": {"type": "float", "width": 60}, - "type": "float" + "type": "float", + "columnWidth": 90, + "format": {"type": "duration", "args": [0, "short"]} }, { "id": "resolution", "title": "Resolution", - "sort": {"type": "integer", "width": 90}, - "type": "integer" + "type": ["integer"], + "columnWidth": 90 + }, + { + "id": "aspectratio", + "title": "Aspect Ratio", + "type": "float", + "columnWidth": 90, + "format": {"type": "unit", "args": [":1"]} }, { "id": "pixels", "title": "Pixels", "type": "integer", - "group": false, - "sort": {"type": "integer", "width": 60}, - "auto": true + "columnWidth": 90, + "format": {"type": "value", "args": ["px"]} + }, + { + "id": "hue", + "title": "Hue", + "type": "hue", + "columnWidth": 90, + "format": {"type": "color", "args": ["hue"]} + }, + { + "id": "saturation", + "title": "Saturation", + "type": "float", + "columnWidth": 90, + "format": {"type": "color", "args": ["greyscale"]} + }, + { + "id": "lightness", + "title": "Lightness", + "type": "float", + "columnWidth": 90, + "format": {"type": "color", "args": ["greyscale"]} + }, + { + "id": "volume", + "title": "Volume", + "type": "float", + "columnWidth": 60 + }, + { + "id": "numberofcuts", + "title": "Number of Cuts", + "type": "integer", + "columnWidth": 60, + "value": {"key": "cuts", "type": "length"} + }, + { + "id": "cutsperminute", + "title": "Cuts per Minute", + "type": "float", + "columnWidth": 60, + "value": {"key": "cuts", "type": "lengthperminute"} + }, + { + "id": "words", + "title": "Words", + "type": "integer", + "columnWidth": 60, + "value": {"layer": "subtitles", "type": "words"} + }, + { + "id": "wordsperminute", + "title": "Words per Minute", + "type": "float", + "columnWidth": 60, + "value": {"layer": "subtitles", "type": "wordsperminute"} }, { "id": "size", "title": "Size", - "sort": {"type": "integer", "width": 60}, - "type": "integer" + "type": "integer", + "columnWidth": 60, + "format": {"type": "value", "args": ["B"]}, + "rightsLevel": 1 }, { "id": "bitrate", "title": "Bitrate", - "sort": {"type": "integer", "width": 60}, - "type": "integer" + "type": "integer", + "columnWidth": 60, + "format": {"type": "unit", "args": ["kbps"]} }, { - "id": "files", - "title": "Files", - "sort": {"type": "integer", "width": 60}, - "type": "integer" + "id": "numberoffiles", + "title": "Number of Files", + "type": "integer", + "columnWidth": 60, + "value": {"key": "files", "type": "length"}, + "rightsLevel": 1 }, { "id": "filename", "title": "Filename", - "sort": {"type": "string", "width": 180}, - "type": "string" + "type": ["string"], + "find": true, + "rightsLevel": 1 }, { "id": "published", "title": "Date Published", - "sort": {"type": "date", "width": 90}, - "type": "date" + "type": "date", + "columnWidth": 90 }, { "id": "modified", "title": "Date Modified", - "sort": {"type": "date", "width": 90}, - "type": "date" + "type": "date", + "columnWidth": 90 }, { "id": "accessed", "title": "Date Accessed", - "sort": {"type": "date", "width": 90}, - "type": "date" + "type": "date", + "columnWidth": 90 }, { "id": "viewed", "title": "Date Viewed", - "sort": {"type": "date", "width": 90}, - "type": "date" + "type": "date", + "columnWidth": 90 }, { "id": "popularity", "title": "Popularity", - "sort": {"type": "float", "width": 60}, - "type": "float" + "type": "integer", + "columnWidth": 60, + "format": {"type": "percent", "args": ["auto", 2]} } ], "itemName": { @@ -384,8 +421,29 @@ {"id": "files", "title": "Files", "admin": true} ], "layers": [ - {"id": "privatenotes", "title": "Private Notes", "type": "text", "private": true}, - {"id": "publicnotes", "title": "Public Notes", "type": "text"} + { + "id": "privatenotes", + "title": "Private Notes", + "type": "text", + "overlap": true, + "private": true + }, + { + "id": "publicnotes", + "title": "Public Notes", + "overlap": true, + "type": "text" + }, + { + "id": "subtitles", + "title": "Subtitles", + "type": "text", + "overlay": true, + "sort": [ + {"id": "words", "title": "Words", "type": "words"}, + {"id": "wordsperminute", "title": "Words per Minute", "type": "wordsperminute"} + ] + } ], "listViews": [ {"id": "list", "title": "as List"}, @@ -499,7 +557,7 @@ "listQuery": {"conditions": [], "operator": ""}, "lists": { "": { - "columns": ["id", "title", "director", "country", "year", "language", "runtime", "genre"], + "columns": ["title", "director", "country", "year", "language", "runtime", "genre"], "columnWidth": {}, "listView": "icons", "selected": [], @@ -535,5 +593,6 @@ "videoSize": "small" }, "username": "" - } + }, + "userLevels": ["guest", "member", "staff", "admin"] } diff --git a/static/js/pandora.js b/static/js/pandora.js index f206fb5d..1a34b524 100755 --- a/static/js/pandora.js +++ b/static/js/pandora.js @@ -9,6 +9,10 @@ var pandora = new Ox.App({ //Ox.print('data', data); + // fixme: never set ui.videoPosition to 0 ... set to null a.k.a. delete + // fixme: sort=-director doesn't work + // fixme: don't reload full right panel on sortSelect + var app = { $ui: { body: $('body'), @@ -21,10 +25,7 @@ var pandora = new Ox.App({ requests: {}, ui: { findKeys: $.map(data.config.itemKeys, function(key, i) { - return 'find' in key ? $.extend({ - id: key.id, - title: key.title - }, key.find) : null; + return key.find ? key : null; }), infoRatio: 16 / 9, scrollbarSize: $.browser.mozilla ? 16 : 12, @@ -55,10 +56,7 @@ var pandora = new Ox.App({ }, selectedMovies: [], sortKeys: $.map(data.config.itemKeys, function(key, i) { - return 'sort' in key ? $.extend({ - id: key.id, - title: key.title - }, key.sort) : null; + return key.columnWidth ? key : null; }) }, user: data.user @@ -660,6 +658,62 @@ var pandora = new Ox.App({ }) return that; }, + filter: function() { + var that = new Ox.Filter({ + findKeys: $.map(app.config.itemKeys, function(key) { + return { + autocomplete: key.autocomplete, + autocompleteSortKey: key.autocompleteSortKey, + format: key.format, + id: key.id, + title: key.title, + type: key.type + }; + }), + sortKeys: app.ui.sortKeys, + viewKeys: app.config.listViews + }); + return that; + }, + filterDialog: function() { + var that = new Ox.Dialog({ + buttons: [ + new Ox.Button({ + id: 'debug', + title: 'Debug', + }) + .bindEvent({ + click: function() { + alert(JSON.stringify(app.$ui.filter.options('query'))); + } + }), + new Ox.Button({ + id: 'cancel', + title: 'Cancel' + }) + .bindEvent({ + click: function() { + app.$ui.filterDialog.close(); + } + }), + new Ox.Button({ + id: 'save', + title: 'Save' + }) + .bindEvent({ + click: function() { + app.$ui.filterDialog.close(); + } + }) + ], + content: app.$ui.filter = new ui.filter(), + height: 264, + keys: {enter: 'save', escape: 'cancel'}, + title: 'Advanced Find', + width: 616 + app.ui.scrollbarSize + }); + return that; + }, findElement: function() { var findKey = '', findValue = ''; @@ -688,29 +742,35 @@ var pandora = new Ox.App({ ] : [], [ app.$ui.findSelect = new Ox.Select({ id: 'select', - items: $.map(app.ui.findKeys, function(key, i) { + items: $.merge($.map(app.ui.findKeys, function(key, i) { return { id: key.id, checked: key.id == findKey, title: 'Find: ' + key.title }; - }), + }), [{}, { + id: 'advanced', + title: 'Find: Advanced' + }]), overlap: 'right', width: 112 }) .bindEvent({ change: function(event, data) { var key = data.selected[0].id; - if (!app.user.ui.findQuery.conditions.length) { // fixme: can this case happen at all? - app.user.ui.findQuery.conditions = [{key: key, value: '', operator: ''}]; + if (key == 'advanced') { + app.$ui.filterDialog = ui.filterDialog().open(); } else { - app.user.ui.findQuery.conditions[0].key = key; + if (!app.user.ui.findQuery.conditions.length) { // fixme: can this case happen at all? + app.user.ui.findQuery.conditions = [{key: key, value: '', operator: ''}]; + } else { + app.user.ui.findQuery.conditions[0].key = key; + } + app.$ui.mainMenu.checkItem('findMenu_find_' + key); + app.$ui.findInput.options({ + autocomplete: autocompleteFunction() + }).focus(); } - app.$ui.mainMenu.checkItem('findMenu_find_' + key); - app.$ui.findInput.options({ - autocomplete: autocompleteFunction() - }).focus(); - //Ox.print(app.$ui.findInput.options('autocomplete').toString()) } }), app.$ui.findInput = new Ox.Input({ @@ -1139,31 +1199,7 @@ var pandora = new Ox.App({ click: function(event, data) { var $list = app.$ui.folderList[id]; if (data.key == 'type') { - var $dialog = new Ox.Dialog({ - buttons: [ - new Ox.Button({ - id: 'cancel', - title: 'Cancel' - }).bindEvent('click', function() { - $dialog.close(); - }), - new Ox.Button({ - id: 'save', - title: 'Save' - }).bindEvent('click', function() { - $dialog.close(); - }) - ], - content: new Ox.Filter({ - keys: $.map(app.config.sortKeys, function(key) { - return {id: key.id, title: key.title, type: 'string'} - }) - }), - height: 200, - keys: {enter: 'save', escape: 'cancel'}, - title: 'Advanced Find', - width: 616 + app.ui.scrollbarSize - }).open(); + app.$ui.filterDialog = ui.filterDialog().open(); } else if (data.key == 'status') { pandora.api.editList({ id: data.id, @@ -1869,16 +1905,22 @@ var pandora = new Ox.App({ that = new Ox.TextList({ columns: $.map(app.ui.sortKeys, function(key, i) { var position = app.user.ui.lists[app.user.ui.list].columns.indexOf(key.id); - Ox.print(position, '++++', key.id, app.user.ui.lists[app.user.ui.list].columnWidth[key.id], key.width, '||:', app.user.ui.lists[app.user.ui.list].columnWidth[key.id] || key.width) - return $.extend($.extend({}, key), { - align: getAlignment(key.id), - defaultWidth: key.width, + return { + align: ['string', 'text'].indexOf( + Ox.isArray(key.type) ? key.type[0]: key.type + ) > -1 ? 'left' : 'right', + defaultWidth: key.columnWidth, + format: key.format, + id: key.id, operator: getSortOperator(key.id), position: position, + removable: !key.columnRequired, + title: key.title, + type: key.type, unique: key.id == 'id', visible: position > -1, - width: app.user.ui.lists[app.user.ui.list].columnWidth[key.id] || key.width - }); + width: app.user.ui.lists[app.user.ui.list].columnWidth[key.id] || key.columnWidth + }; }), columnsMovable: true, columnsRemovable: true, @@ -3206,12 +3248,6 @@ var pandora = new Ox.App({ app.user.ui.showMovies && app.$ui.contentPanel.size(0, 112 + app.ui.scrollbarSize); } - function getAlignment(key) { // fixme: make static - return ['person', 'string', 'text', 'title'].indexOf( - Ox.getObjectById(app.ui.sortKeys, key).type - ) > -1 ? 'left' : 'right'; - } - function getListData() { var data = {}; if (app.user.ui.list) { @@ -3261,9 +3297,10 @@ var pandora = new Ox.App({ } function getSortOperator(key) { // fixme: make static - return ['person', 'string', 'text', 'title'].indexOf( - Ox.getObjectById(app.ui.sortKeys, key).type - ) > -1 ? '' : '-'; + var type = Ox.getObjectById(app.config.itemKeys, key).type; + return ['hue', 'string', 'text'].indexOf( + Ox.isArray(type) ? type[0] : type + ) > -1 ? '+' : '-'; } function reloadGroups(i) { @@ -3560,7 +3597,7 @@ var pandora = new Ox.App({ UI.set(['lists', app.user.ui.list, 'sort'].join('|'), $.map(query.sort.split(','), function(v, i) { var hasOperator = '+-'.indexOf(v[0]) > -1, key = hasOperator ? query.sort.substr(1) : query.sort, - operator = hasOperator ? v[0].replace('+', '') : getSortOperator(key); + operator = hasOperator ? v[0]/*.replace('+', '')*/ : getSortOperator(key); return { key: key, operator: operator @@ -3596,10 +3633,12 @@ var pandora = new Ox.App({ toString: function() { //Ox.print('tS', app.user.ui.find) + var sort = app.user.ui.lists[app.user.ui.list].sort[0]; + key = sort.key, + operator = sort.operator; return '?' + Ox.serialize({ find: constructFind(Query.toObject()), - sort: app.user.ui.lists[app.user.ui.list].sort[0].operator + - app.user.ui.lists[app.user.ui.list].sort[0].key, + sort: (operator == getSortOperator(key) ? '' : operator) + key, view: app.user.ui.lists[app.user.ui.list].listView }); } @@ -3612,28 +3651,27 @@ var pandora = new Ox.App({ return { set: function(obj) { if (arguments.length == 2) { + // translate (key, value) to {key: value} var obj_ = {}; obj_[arguments[0]] = arguments[1]; obj = obj_; } $.each(obj, function(key, val) { Ox.print('key', key, 'val', val) - keys = key.split('|'); - if (keys.length == 1) { - app.user.ui[keys[0]] = val; - } else if (keys.length == 2) { - app.user.ui[keys[0]][keys[1]] = val; - } else if (keys.length == 3) { - app.user.ui[keys[0]][keys[1]][keys[2]] = val; - } else if (keys.length == 4) { - app.user.ui[keys[0]][keys[1]][keys[2]][keys[3]] = val; - } else if (keys.length == 5) { - app.user.ui[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]] = val; - } else if (keys.length == 6) { - app.user.ui[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]][keys[5]] = val; + var i = 0, + keys = key.split('|'), + old = app.user.ui; + while (i < keys.length - 1) { + old = old[keys[i]]; + i++; + } + if (old[keys[i]] !== val) { + old[keys[i]] = val; + } else { + delete obj[key]; } }); - pandora.api.setUI(obj); + Ox.length(obj) && pandora.api.setUI(obj); //alert('set ' + JSON.stringify(obj)) } }