From 8ec2e71e4239f184ac5b8b5d2c1cdcf48df10338 Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 27 Dec 2011 12:24:49 +0530
Subject: [PATCH] add info view for padma
---
pandora/item/models.py | 6 +-
static/js/pandora.js | 7 +
static/js/pandora/infoView.js | 2 +-
static/js/pandora/infoView.padma.js | 623 ++++++++++++++++++++++++++++
4 files changed, 636 insertions(+), 2 deletions(-)
create mode 100644 static/js/pandora/infoView.padma.js
diff --git a/pandora/item/models.py b/pandora/item/models.py
index 22f6d25fa..9f88eff86 100644
--- a/pandora/item/models.py
+++ b/pandora/item/models.py
@@ -141,7 +141,7 @@ class Item(models.Model):
#while metadata is updated, files are set to rendered=False
rendered = models.BooleanField(default=False, db_index=True)
#should be set based on user
- level = models.IntegerField(default=4, db_index=True)
+ level = models.IntegerField(db_index=True)
itemId = models.CharField(max_length=128, unique=True, blank=True)
oxdbId = models.CharField(max_length=42, unique=True, blank=True, null=True)
@@ -260,6 +260,8 @@ class Item(models.Model):
if not self.id:
if self.user:
self.level = settings.CONFIG['rightsLevel'][self.user.get_profile().get_level()]
+ else:
+ self.level = settings.CONFIG['rightsLevel']['member']
if not self.itemId:
self.itemId = str(uuid.uuid1())
super(Item, self).save(*args, **kwargs)
@@ -441,6 +443,8 @@ class Item(models.Model):
'rendered': self.rendered,
'rightslevel': self.level
}
+ if self.user:
+ i['user'] = self.user.username
i.update(self.external_data)
i.update(self.data)
for k in settings.CONFIG['itemKeys']:
diff --git a/static/js/pandora.js b/static/js/pandora.js
index 5d8291cd2..abe406e9f 100644
--- a/static/js/pandora.js
+++ b/static/js/pandora.js
@@ -152,6 +152,13 @@ appPanel
});
loadPandoraFiles(function() {
initPandora(data);
+ if (localStorage && localStorage.pandoraLocal) {
+ window.pandora.local = Ox.API({
+ 'url': localStorage.pandoraLocal + '/api/'
+ }, function() {
+ pandora.site.site.videoprefix = localStorage.pandoraLocal;
+ });
+ }
});
}
});
diff --git a/static/js/pandora/infoView.js b/static/js/pandora/infoView.js
index 83fc06732..5b60d5399 100644
--- a/static/js/pandora/infoView.js
+++ b/static/js/pandora/infoView.js
@@ -782,7 +782,7 @@ pandora.ui.infoView = function(data) {
.data({OxColor: $rightsLevelElement.data('OxColor')})
.bindEvent({
change: function(event) {
- var rightsLevel = event.value
+ var rightsLevel = event.value;
$rightsLevelElement = getRightsLevelElement(rightsLevel);
$rightsLevelSelect
.css({background: $rightsLevelElement.css('background')})
diff --git a/static/js/pandora/infoView.padma.js b/static/js/pandora/infoView.padma.js
new file mode 100644
index 000000000..1d1801ba5
--- /dev/null
+++ b/static/js/pandora/infoView.padma.js
@@ -0,0 +1,623 @@
+'use strict';
+
+pandora.ui.infoView = function(data) {
+
+ // fixme: given that currently, the info view doesn't scroll into view nicely
+ // when collapsing the movies browser, the info view should become a split panel
+
+ var ui = pandora.user.ui,
+ canEdit = pandora.site.capabilities.canEditMetadata[pandora.user.level],
+ css = {
+ marginTop: '4px',
+ textAlign: 'justify',
+ MozUserSelect: 'text',
+ WebkitUserSelect: 'text'
+ },
+ iconRatio = ui.icons == 'posters'
+ ? (ui.showSitePoster ? 5/8 : data.posterRatio) : 1,
+ iconSize = ui.infoIconSize,
+ iconWidth = iconRatio > 1 ? iconSize : Math.round(iconSize * iconRatio),
+ iconHeight = iconRatio < 1 ? iconSize : Math.round(iconSize / iconRatio),
+ iconLeft = iconSize == 256 ? Math.floor((iconSize - iconWidth) / 2) : 0,
+ borderRadius = ui.icons == 'posters' ? 0 : iconSize / 8,
+ isEditable = canEdit,
+ listWidth = 144 + Ox.UI.SCROLLBAR_SIZE,
+ margin = 16,
+ statisticsWidth = 128,
+ uid = Ox.uid(),
+
+ that = Ox.Element(),
+
+ $list,
+
+ $info = $('
')
+ .css({
+ position: 'absolute',
+ left: canEdit && !ui.showIconBrowser ? -listWidth + 'px' : 0,
+ top: 0,
+ right: 0,
+ })
+ .appendTo(that.$element),
+
+ $data = Ox.Container()
+ .css({
+ position: 'absolute',
+ left: (canEdit ? listWidth : 0) + 'px',
+ top: 0,
+ right: 0,
+ height: pandora.$ui.contentPanel.size(1) + 'px'
+ })
+ .appendTo($info),
+
+ $icon = Ox.Element({
+ element: '
![]()
',
+ })
+ .attr({
+ src: '/' + data.id + '/' + (
+ ui.icons == 'posters'
+ ? (ui.showSitePoster ? 'siteposter' : 'poster') : 'icon'
+ ) + '512.jpg?' + uid
+ })
+ .css({
+ position: 'absolute',
+ left: margin + iconLeft + 'px',
+ top: margin + 'px',
+ width: iconWidth + 'px',
+ height: iconHeight + 'px',
+ borderRadius: borderRadius + 'px',
+ cursor: 'pointer'
+ })
+ .bindEvent({
+ singleclick: toggleIconSize
+ })
+ .appendTo($data.$element),
+
+ $reflection = $('
')
+ .addClass('OxReflection')
+ .css({
+ position: 'absolute',
+ left: margin + 'px',
+ top: margin + iconHeight + 'px',
+ width: iconSize + 'px',
+ height: iconSize / 2 + 'px',
+ overflow: 'hidden'
+ })
+ .appendTo($data.$element),
+
+ $reflectionIcon = $('
![]()
')
+ .attr({
+ src: '/' + data.id + '/' + (
+ ui.icons == 'posters' ? 'poster' : 'icon'
+ ) + '512.jpg?' + uid
+ })
+ .css({
+ position: 'absolute',
+ left: iconLeft + 'px',
+ width: iconWidth + 'px',
+ height: iconHeight + 'px',
+ borderRadius: borderRadius + 'px'
+ })
+ .appendTo($reflection),
+
+ $reflectionGradient = $('
')
+ .css({
+ position: 'absolute',
+ width: iconSize + 'px',
+ height: iconSize / 2 + 'px'
+ })
+ .appendTo($reflection),
+
+ $text = Ox.Element({
+ tooltip: canEdit && !isEditable ? 'Doubleclick to reload metadata' : ''
+ })
+ .css({
+ position: 'absolute',
+ left: margin + (iconSize == 256 ? 256 : iconWidth) + margin + 'px',
+ top: margin + 'px',
+ right: margin + statisticsWidth + margin + 'px',
+ //background: 'green'
+ })
+ .bindEvent(canEdit && !isEditable ? {
+ doubleclick: reloadMetadata
+ } : {})
+ .appendTo($data.$element),
+
+ $statistics = $('
')
+ .css({
+ position: 'absolute',
+ width: statisticsWidth + 'px',
+ top: margin + 'px',
+ right: margin + 'px'
+ })
+ .appendTo($data.$element),
+
+ $capabilities,
+
+ $browserImages = [];
+
+ pandora.createLinks($text);
+
+ // Title -------------------------------------------------------------------
+
+ $('
')
+ .css({
+ marginTop: '-2px'
+ })
+ .append(
+ Ox.Editable({
+ editable: isEditable,
+ format: function(value) {
+ return formatTitle(value);
+ },
+ tooltip: isEditable ? 'Doubleclick to edit' : '',
+ value: data.title
+ })
+ .css({
+ display: 'inline-block',
+ marginBottom: '-3px',
+ fontWeight: 'bold',
+ fontSize: '13px',
+ MozUserSelect: 'text',
+ WebkitUserSelect: 'text'
+ })
+ .bindEvent({
+ submit: function(event) {
+ editMetadata('title', event.value);
+ }
+ })
+ .appendTo($text)
+ )
+ .appendTo($text);
+
+ // Director ----------------------------------------------------------------
+
+ if (data.director || isEditable) {
+ $('
')
+ .css({
+ marginTop: '2px'
+ })
+ .append(
+ Ox.Editable({
+ clickLink: pandora.clickLink,
+ editable: isEditable,
+ format: function(value) {
+ return formatValue(value.split(', '), 'name');
+ },
+ placeholder: formatLight('Unknown Director'),
+ tooltip: isEditable ? 'Doubleclick to edit' : '',
+ value: data.director ? data.director.join(', ') : 'Unknown Director'
+ })
+ .css({
+ display: 'inline-block',
+ marginBottom: '-3px',
+ fontWeight: 'bold',
+ fontSize: '13px',
+ MozUserSelect: 'text',
+ WebkitUserSelect: 'text'
+ })
+ .bindEvent({
+ submit: function(event) {
+ editMetadata('director', event.value);
+ }
+ })
+ )
+ .appendTo($text);
+ }
+
+ // Country, Year, Language, Runtime ----------------------------------------
+
+ if (isEditable) {
+ var $div = $('
')
+ .css(css)
+ .appendTo($text);
+ ['country', 'year'].forEach(function(key) {
+ $('
')
+ .css({float: 'left'})
+ .html(formatKey(key).replace('', ' '))
+ .appendTo($div);
+ Ox.Editable({
+ clickLink: pandora.clickLink,
+ format: function(value) {
+ return formatValue(value.split(', '), key)
+ },
+ placeholder: formatLight('unknown'),
+ tooltip: 'Doubleclick to edit',
+ value: key == 'country'
+ ? (data[key] ? data[key].join(', ') : [''])
+ : data[key] || ''
+ })
+ .css({float: 'left'})
+ .bindEvent({
+ submit: function(event) {
+ editMetadata(key, event.value);
+ }
+ })
+ .appendTo($div);
+ key == 'country' && $('
').css({float: 'left'}).html('; ').appendTo($div);
+ });
+ } else if (data.country || data.year || data.language || data.runtime) {
+ var html = [];
+ ['country', 'year', 'language', 'runtime'].forEach(function(key) {
+ if (data[key]) {
+ html.push(
+ formatKey(key)
+ + (key == 'runtime'
+ ? Math.round(data[key] / 60) + ' min'
+ : formatValue(data[key], key))
+ )
+ }
+ });
+ $('
').css(css).html(html.join('; ')).appendTo($text);
+ }
+ $('
').html('
').appendTo($text);
+ //Categories
+ $('
')
+ .css(css)
+ .html(
+ formatKey('categories') + formatValue(data['category'], 'category')
+ )
+ .appendTo($text);
+
+ [
+ 'source',
+ 'collection',
+ 'category',
+ 'user',
+ 'location',
+ ].forEach(function(key) {
+ $('
')
+ .html(
+ formatKey(key=='user'?'contributor':key) + formatValue(data[key], key)
+ )
+ .appendTo($text);
+ });
+ [
+ 'date',
+ 'modified',
+ 'accessed',
+ 'created',
+ ].forEach(function(key) {
+ $('
')
+ .html(
+ formatKey(key=='user'?'contributor':key) + data[key]
+ )
+ .appendTo($text);
+ });
+ data.description && $('
')
+ .css(css)
+ .html(
+ formatKey('description') + data.description
+ )
+ .appendTo($text);
+ $('
').css({height: '16px'}).appendTo($text);
+
+ // Hue, Saturation, Lightness, Volume --------------------------------------
+
+ ['hue', 'saturation', 'lightness', 'volume'].forEach(function(key) {
+ $('
')
+ .css({marginBottom: '4px'})
+ .append(formatKey(key, true))
+ .append(
+ Ox.Theme.formatColor(
+ data[key] || 0, key == 'volume' ? 'lightness' : key
+ ).css({textAlign: 'right'})
+ )
+ .appendTo($statistics);
+ });
+
+ // Rights Level ------------------------------------------------------------
+
+ var $rightsLevel = $('
');
+ $('
')
+ .css({marginBottom: '4px'})
+ .append(formatKey('Rights Level', true))
+ .append($rightsLevel)
+ .appendTo($statistics);
+ renderRightsLevel();
+
+ // Notes -------------------------------------------------------------------
+
+ if (canEdit) {
+
+ $('
')
+ .css({marginBottom: '4px'})
+ .append(formatKey('Notes', true))
+ .append(
+ Ox.Editable({
+ height: 128,
+ placeholder: formatLight('No notes'),
+ tooltip: 'Doubleclick to edit',
+ type: 'textarea',
+ value: data.notes,
+ width: 128
+ })
+ .bindEvent({
+ submit: function(event) {
+ pandora.api.edit({
+ id: data.id,
+ notes: event.value
+ }, function(result) {
+ // ...
+ });
+ }
+ })
+ )
+ .appendTo($statistics);
+
+ }
+
+ $('
').css({height: '16px'}).appendTo($statistics);
+
+ function editMetadata(key, value) {
+ if (value != data[key]) {
+ var edit = {id: data.id};
+ if (key == 'title') {
+ Ox.extend(edit, parseTitle(value));
+ } else if (key == 'director' || key == 'country') {
+ edit[key] = value.split(', ');
+ } else {
+ edit[key] = value;
+ }
+ pandora.api.edit(edit, function(result) {
+ if (result.data.id != data.id) {
+ Ox.Request.clearCache(); // fixme: too much
+ pandora.UI.set({item: result.data.id});
+ pandora.$ui.browser.value(data.id, 'id', result.data.id);
+ }
+ // FIXME: value function should accept {k: v, ...}
+ pandora.$ui.browser.value(result.data.id, 'title', result.data.title);
+ pandora.$ui.browser.value(result.data.id, 'director', result.data.director);
+ pandora.$ui.browser.value(result.data.id, 'country', result.data.country);
+ pandora.$ui.browser.value(result.data.id, 'year', result.data.year);
+ //pandora.$ui.contentPanel.replaceElement(0, pandora.$ui.browser = pandora.ui.browser());
+ });
+ }
+ }
+
+ function formatKey(key, isStatistics) {
+ return isStatistics
+ ? $('
').css({marginBottom: '4px', fontWeight: 'bold'}).html(Ox.toTitleCase(key))
+ : '
' + Ox.toTitleCase(key) + ': ';
+ }
+
+ function formatLight(str) {
+ return '
' + str + '';
+ }
+
+ function formatTitle(title) {
+ var match = /(\(S\d{2}E\d{2}\))/.exec(title);
+ if (match) {
+ title = title.replace(match[0], formatLight(match[0]));
+ }
+ return title + (
+ data.originalTitle && data.originalTitle != title
+ ? ' ' + formatLight('(' + data.originalTitle + ')') : ''
+ );
+ }
+
+ function formatValue(value, key) {
+ return (Ox.isArray(value) ? value : [value]).map(function(value) {
+ return key ?
+ '
' + value + ''
+ : value;
+ }).join(', ');
+ }
+
+ function getRightsLevelElement(rightsLevel) {
+ return Ox.Theme.formatColorLevel(
+ rightsLevel,
+ pandora.site.rightsLevels.map(function(rightsLevel) {
+ return rightsLevel.name;
+ })
+ );
+ }
+
+ function parseTitle(title) {
+ var data = {title: title},
+ match = /(\(S(\d{2})E(\d{2})\))/.exec(title),
+ split;
+ if (match) {
+ data.season = parseInt(match[2], 10);
+ data.episode = parseInt(match[3], 10);
+ split = title.split(match[1]);
+ data.seriesTitle = split[0].trim();
+ data.episodeTitle = split[1].trim();
+ }
+ return data;
+ }
+
+ function reloadMetadata() {
+ var item = ui.item;
+ // fixme: maybe there's a better method name for this?
+ pandora.api.updateExternalData({
+ id: ui.item
+ }, function(result) {
+ Ox.Request.clearCache(item);
+ if (ui.item == item && ui.itemView == 'info') {
+ pandora.$ui.contentPanel.replaceElement(
+ 1, pandora.$ui.item = pandora.ui.item()
+ );
+ }
+ });
+ }
+
+ function renderCapabilities(rightsLevel) {
+ var capabilities = Ox.merge(
+ canEdit ? [{name: 'canSeeItem', symbol: 'Find'}] : [],
+ [
+ {name: 'canPlayClips', symbol: 'PlayInToOut'},
+ {name: 'canPlayVideo', symbol: 'Play'},
+ {name: 'canDownloadVideo', symbol: 'Download'}
+ ]
+ ),
+ userLevels = canEdit ? pandora.site.userLevels : [pandora.user.level];
+ $capabilities.empty();
+ userLevels.forEach(function(userLevel, i) {
+ var $element,
+ $line = $('
')
+ .css({
+ height: '16px',
+ marginBottom: '4px'
+ })
+ .appendTo($capabilities);
+ if (canEdit) {
+ $element = Ox.Theme.formatColorLevel(i, userLevels.map(function(userLevel) {
+ return Ox.toTitleCase(userLevel);
+ }), [0, 240]);
+ Ox.Label({
+ textAlign: 'center',
+ title: Ox.toTitleCase(userLevel),
+ width: 60
+ })
+ .addClass('OxColor OxColorGradient')
+ .css({
+ float: 'left',
+ height: '12px',
+ paddingTop: '2px',
+ background: $element.css('background'),
+ fontSize: '8px',
+ color: $element.css('color')
+ })
+ .data({OxColor: $element.data('OxColor')})
+ .appendTo($line);
+ }
+ capabilities.forEach(function(capability) {
+ var hasCapability = pandora.site.capabilities[capability.name][userLevel] >= rightsLevel,
+ $element = Ox.Theme.formatColorLevel(hasCapability, ['', '']);
+ Ox.Button({
+ tooltip: (canEdit ? Ox.toTitleCase(userLevel) : 'You') + ' '
+ + (hasCapability ? 'can' : 'can\'t') + ' '
+ + Ox.map(Ox.toSlashes(capability.name).split('/'), function(word, i) {
+ return i == 0 ? null : word.toLowerCase();
+ }).join(' '),
+ title: capability.symbol,
+ type: 'image'
+ })
+ .addClass('OxColor OxColorGradient')
+ .css({background: $element.css('background')})
+ .css('margin' + (canEdit ? 'Left' : 'Right'), '4px')
+ .data({OxColor: $element.data('OxColor')})
+ .appendTo($line);
+ });
+ if (!canEdit) {
+ Ox.Button({
+ title: 'Help',
+ tooltip: 'About Rights',
+ type: 'image'
+ })
+ .css({marginLeft: '52px'})
+ .bindEvent({
+ click: function() {
+ pandora.UI.set({page: 'rights'});
+ }
+ })
+ .appendTo($line);
+ }
+ });
+ }
+
+ function renderRightsLevel() {
+ var $rightsLevelElement = getRightsLevelElement(data.rightslevel),
+ $rightsLevelSelect;
+ $rightsLevel.empty();
+ if (canEdit) {
+ $rightsLevelSelect = Ox.Select({
+ items: pandora.site.rightsLevels.map(function(rightsLevel, i) {
+ return {id: i, title: rightsLevel.name, checked: i == data.rightslevel};
+ }),
+ width: 128
+ })
+ .addClass('OxColor OxColorGradient')
+ .css({
+ marginBottom: '4px',
+ background: $rightsLevelElement.css('background')
+ })
+ .data({OxColor: $rightsLevelElement.data('OxColor')})
+ .bindEvent({
+ change: function(event) {
+ var rightsLevel = event.value;
+ $rightsLevelElement = getRightsLevelElement(rightsLevel);
+ $rightsLevelSelect
+ .css({background: $rightsLevelElement.css('background')})
+ .data({OxColor: $rightsLevelElement.data('OxColor')})
+ renderCapabilities(rightsLevel);
+ pandora.api.edit({id: data.id, rightslevel: rightsLevel}, function(result) {
+ // ...
+ });
+ }
+ })
+ .appendTo($rightsLevel);
+ } else {
+ $rightsLevelElement
+ .css({
+ marginBottom: '4px'
+ })
+ .appendTo($rightsLevel);
+ }
+ $capabilities = $('
').appendTo($rightsLevel);
+ renderCapabilities(data.rightslevel);
+ }
+
+ function toggleIconSize() {
+ iconSize = iconSize == 256 ? 512 : 256;
+ iconWidth = iconRatio > 1 ? iconSize : Math.round(iconSize * iconRatio);
+ iconHeight = iconRatio < 1 ? iconSize : Math.round(iconSize / iconRatio);
+ iconLeft = iconSize == 256 ? Math.floor((iconSize - iconWidth) / 2) : 0,
+ borderRadius = ui.icons == 'posters' ? 0 : iconSize / 8;
+ $icon.animate({
+ left: margin + iconLeft + 'px',
+ width: iconWidth + 'px',
+ height: iconHeight + 'px',
+ borderRadius: borderRadius + 'px'
+ }, 250);
+ $reflection.animate({
+ top: margin + iconHeight + 'px',
+ width: iconSize + 'px',
+ height: iconSize / 2 + 'px'
+ }, 250);
+ $reflectionIcon.animate({
+ left: iconLeft + 'px',
+ width: iconWidth + 'px',
+ height: iconHeight + 'px',
+ borderRadius: borderRadius + 'px'
+ }, 250);
+ $reflectionGradient.animate({
+ width: iconSize + 'px',
+ height: iconSize / 2 + 'px'
+ }, 250);
+ $text.animate({
+ left: margin + (iconSize == 256 ? 256 : iconWidth) + margin + 'px',
+ }, 250);
+ pandora.UI.set({infoIconSize: iconSize});
+ }
+
+ that.reload = function() {
+ var src = src = '/' + data.id + '/' + (
+ ui.icons == 'posters'
+ ? (ui.showSitePoster ? 'siteposter' : 'poster') : 'icon'
+ ) + '512.jpg?' + Ox.uid()
+ $icon.attr({src: src});
+ $reflectionIcon.attr({src: src});
+ iconSize = iconSize == 256 ? 512 : 256;
+ iconRatio = ui.icons == 'posters'
+ ? (ui.showSitePoster ? 5/8 : data.posterRatio) : 1;
+ toggleIconSize();
+ pandora.user.level == 'admin' && $list.replaceWith($list = renderList());
+ };
+
+ that.resize = function() {
+ var height = pandora.$ui.contentPanel.size(1);
+ $list && $list.css({height: height + 'px'});
+ $data.css({height: height + 'px'});
+ };
+
+ that.bindEvent({
+ pandora_icons: that.reload,
+ pandora_showsiteposter: function() {
+ ui.icons == 'posters' && that.reload();
+ }
+ });
+
+ return that;
+
+}