From 5129b7565008437c05de133971e27897a547bca2 Mon Sep 17 00:00:00 2001 From: j Date: Sat, 13 Jul 2019 16:32:23 +0100 Subject: [PATCH] collection icons --- .../migrations/0004_jsonfield.py | 22 ++ pandora/documentcollection/models.py | 27 +- static/js/collectionIconPanel.js | 249 ++++++++++++++++++ static/js/listDialog.js | 7 +- 4 files changed, 283 insertions(+), 22 deletions(-) create mode 100644 pandora/documentcollection/migrations/0004_jsonfield.py create mode 100644 static/js/collectionIconPanel.js diff --git a/pandora/documentcollection/migrations/0004_jsonfield.py b/pandora/documentcollection/migrations/0004_jsonfield.py new file mode 100644 index 00000000..d76aa109 --- /dev/null +++ b/pandora/documentcollection/migrations/0004_jsonfield.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2018-06-19 17:23 +from __future__ import unicode_literals + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models + +def remove_posterframes(apps, schema_editor): + Collection = apps.get_model("documentcollection", "Collection") + for c in Collection.objects.exclude(poster_frames=None): + c.poster_frames = [] + c.save() + +class Migration(migrations.Migration): + + dependencies = [ + ('documentcollection', '0003_jsonfield'), + ] + + operations = [ + migrations.RunPython(remove_posterframes), + ] diff --git a/pandora/documentcollection/models.py b/pandora/documentcollection/models.py index 014f6bec..74b55b58 100644 --- a/pandora/documentcollection/models.py +++ b/pandora/documentcollection/models.py @@ -265,38 +265,23 @@ class Collection(models.Model): def update_icon(self): frames = [] - #fixme - ''' if not self.poster_frames: - documents = self.get_documents(self.user) + documents = self.get_documents(self.user).all() if documents.count(): poster_frames = [] for i in range(0, documents.count(), max(1, int(documents.count()/4))): poster_frames.append({ - 'document': documents[int(i)].id, - 'position': documents[int(i)].poster_frame + 'document': documents[int(i)].get_id(), + #'page': documents[int(i)] }) self.poster_frames = tuple(poster_frames) self.save() for i in self.poster_frames: from document.models import Document - qs = Document.objects.filter(id=i['document']) + qs = Document.objects.filter(id=ox.fromAZ(i['document'])) if qs.count() > 0: - if i.get('position'): - frame = qs[0].frame(i['position']) - if frame: - frames.append(frame) - ''' - from item.models import Item - for i in self.poster_frames: - try: - qs = Item.objects.filter(public_id=i['item']) - if qs.count() > 0: - frame = qs[0].frame(i['position']) - if frame: - frames.append(frame) - except: - pass + frame = qs[0].thumbnail(size=1024, page=i.get('page')) + frames.append(frame) self.icon.name = self.path('icon.jpg') icon = self.icon.path if frames: diff --git a/static/js/collectionIconPanel.js b/static/js/collectionIconPanel.js new file mode 100644 index 00000000..6ee34e8d --- /dev/null +++ b/static/js/collectionIconPanel.js @@ -0,0 +1,249 @@ +'use strict'; + +pandora.ui.collectionIconPanel = function(listData) { + + var quarter = 0, + quarters = ['top-left', 'top-right', 'bottom-left', 'bottom-right'], + + ui = pandora.user.ui, + folderItems = pandora.getFolderItems(ui.section), + folderItem = folderItems.slice(0, -1), + + + $iconPanel = Ox.Element(), + + $icon = $('') + .attr({ + src: pandora.getListIcon(ui.section, listData.id, 256) + }) + .css({position: 'absolute', borderRadius: '64px', margin: '16px'}) + .appendTo($iconPanel), + + $previewPanel = Ox.Element(), + + $preview, + + $list = Ox.Element(), + + ui = pandora.user.ui, + + that = Ox.SplitPanel({ + elements: [ + { + element: $iconPanel, + size: 280 + }, + { + element: $previewPanel + }, + { + element: $list, + size: 144 + Ox.UI.SCROLLBAR_SIZE + } + ], + orientation: 'horizontal' + }); + + pandora.api['find' + folderItems]({ + query: { + conditions: [{key: 'id', value: listData.id, operator: '=='}], + operator: '&' + }, + keys: ['posterFrames'] + }, function(result) { + + var posterFrames = result.data.items[0].posterFrames, + posterFrame = posterFrames[quarter], + + $interface = Ox.Element({ + tooltip: function(e) { + var quarterName = ($(e.target).attr('id') || '').replace('-', ' '); + return quarterName ? Ox._('Edit ' + quarterName + ' image') : null; + } + }) + .css({ + position: 'absolute', + width: '256px', + height: '256px', + marginLeft: '16px', + marginTop: '16px', + cursor: 'pointer' + }) + .on({ + click: function(e) { + clickIcon(e); + }, + dblclick: function(e) { + clickIcon(e, true); + } + }) + .appendTo($iconPanel); + + renderQuarters(); + + $list = Ox.IconList({ + borderRadius: 16, + item: function(data, sort) { + var infoKey = ['title', 'author'].indexOf(sort[0].key) > -1 + ? pandora.site.documentKeys.filter(function(key) { + return ['year', 'date'].indexOf(key.id) > -1 + }).map(function(key) { + return key.id; + })[0] : sort[0],key, + size = 128; + return { + height: size, + id: data.id, + info: data[infoKey] || '', + title: data.title, + url: pandora.getMediaURL('/documents/' + data.id + '/' + size + 'p.jpg?' + data.modified), + width: size + }; + }, + items: function(data, callback) { + var listData = pandora.getListData(); + pandora.api.findDocuments(Ox.extend(data, { + query: { + conditions: [{key: 'collection', value: listData.id, operator: '=='}], + operator: '&' + } + }), callback); + }, + keys: ['duration', 'id', 'modified', 'title'], + max: 1, + min: 1, + //orientation: 'vertical', + selected: posterFrame ? [posterFrame.document] : [], + size: 128, + sort: ui.collectionSort, + unique: 'id' + }) + //.css({width: '144px'}) + .bindEvent({ + open: function(data) { + setPosterFrame(data.ids[0], $list.value(data.ids[0], 'posterFrame')) + }, + select: function(data) { + renderPreview($list.value(data.ids[0])); + } + }) + .bindEventOnce({ + load: function() { + var itemData; + if (!posterFrame) { + itemData = $list.value(0); + $list.options({selected: [itemData.id]}); + } else { + itemData = $list.value(posterFrame.item); + } + itemData && renderPreview(itemData); + } + }) + .gainFocus(); + + that.replaceElement(2, $list); + + function clickIcon(e, isDoubleClick) { + quarter = quarters.indexOf($(e.target).attr('id')); + renderQuarters(); + if (isDoubleClick && posterFrames.length) { + var item = posterFrames[quarter].item; + $list.options({selected: [item]}); + renderPreview($list.value(item), posterFrames[quarter].page); + } + } + + function renderPreview(itemData, page) { + var size = 256; + if (itemData.id) { + $preview = Ox.Element('').attr({ + src: pandora.getMediaURL('/documents/' + itemData.id + '/' + size + 'p.jpg?' + itemData.modified), + }) + .css({ + width: size + 'px', + height: size + 'px', + marginLeft: '8px', marginTop: '16px', overflow: 'hidden' + }) + .on({ + click: function(d) { + setPosterFrame(itemData.id); + } + }); + } else { + $preview = Ox.Element() + } + $previewPanel.empty().append($preview); + } + + function renderQuarters() { + $interface.empty(); + quarters.forEach(function(q, i) { + $interface.append( + $('
') + .attr({id: q}) + .css({ + float: 'left', + width: '126px', + height: '126px', + border: '1px solid rgba(255, 255, 255, ' + (i == quarter ? 0.75 : 0) + ')', + background: 'rgba(0, 0, 0, ' + (i == quarter ? 0 : 0.75) + ')' + }) + .css('border-' + q + '-radius', '64px') + ); + }); + } + + function setPosterFrame(document, page) { + var posterFrame = {document: document, page: page}; + if (posterFrames.length) { + posterFrames[quarter] = posterFrame; + } else { + posterFrames = Ox.range(4).map(function() { return Ox.clone(posterFrame); } ); + } + pandora.api['edit' + folderItem]({ + id: listData.id, + posterFrames: posterFrames + }, function() { + $icon.attr({ + src: pandora.getListIcon(ui.section, listData.id, 256) + }); + pandora.$ui.folderList[listData.folder].$element + .find('img[src*="' + + pandora.getMediaURL('/' + encodeURIComponent(listData.id)) + + '/"]' + ) + .attr({ + src: pandora.getListIcon(ui.section, listData.id, 256) + }); + pandora.$ui.info.updateListInfo(); + }); + $preview.options({page: page}); + } + + }); + + function renderFrame() { + $frame.css({borderRadius: 0}); + $frame.css('border-' + quarters[quarter] + '-radius', '128px'); + } + + that.updateQuery = function(key, value) { + $list.options({ + items: function(data, callback) { + pandora.api.find(Ox.extend(data, { + query: { + conditions: [{key: 'collection', value: listData.id, operator: '=='}].concat( + value !== '' + ? [{key: key, value: value, operator: '='}] + : [] + ), + operator: '&' + } + }), callback); + } + }); + }; + + return that; + +} diff --git a/static/js/listDialog.js b/static/js/listDialog.js index 41ba382d..8187bbfa 100644 --- a/static/js/listDialog.js +++ b/static/js/listDialog.js @@ -22,7 +22,12 @@ pandora.ui.listDialog = function(section) { if (id == 'general') { return pandora.ui.listGeneralPanel(listData); } else if (id == 'icon') { - return pandora.$ui.listIconPanel = pandora.ui.listIconPanel(listData); + if (pandora.user.ui.section == 'documents') { + pandora.$ui.listIconPanel = pandora.ui.collectionIconPanel(listData); + } else { + pandora.$ui.listIconPanel = pandora.ui.listIconPanel(listData); + } + return pandora.$ui.listIconPanel } else if (id == 'query') { return pandora.$ui.filterForm = (pandora.user.ui.section == 'documents' ? pandora.ui.documentFilterForm