better demo config and info view

always pass oxdbId to poster script
use 0xdb like poster script for demo
This commit is contained in:
j 2012-06-13 17:59:10 +02:00
parent e4d0660074
commit 70892dd463
9 changed files with 183 additions and 316 deletions

View file

@ -62,7 +62,7 @@ def reloader_thread():
load_config()
_config_mtime = mtime
except:
print "reloading config failed"
sys.stderr.write("reloading config failed\n")
time.sleep(1)
def update_static():

View file

@ -112,7 +112,7 @@ def getPage(request):
name = data['name']
page, created = models.Page.objects.get_or_create(name=name)
if created:
page.text= 'Insert text here'
page.text= ''
page.save()
response = json_response({'name': page.name, 'text': page.text})
return render_to_json_response(response)

View file

@ -8,7 +8,7 @@
{"key": "title", "operator": "+"}
],
"annotations": {
"showUsers": true
"showUsers": false
},
"cantPlay": {
"icon": "",
@ -66,17 +66,14 @@
text of clips. Excluding a layer from this list means it will not be
included in find annotations. // FIXME: the last bit is not implemented.
*/
"clipLayers": ["transcripts", "keywords", "places", "events", "descriptions"],
"clipLayers": ["publicnotes", "keywords", "subtitles"],
// fixme: either this, or filter: true in itemKeys, but not both
"filters": [
{"id": "source", "title": "Sources", "type": "string"},
{"id": "project", "title": "Projects", "type": "string"},
{"id": "topic", "title": "Topics", "type": "string"},
{"id": "name", "title": "People", "type": "string"},
{"id": "director", "title": "Director", "type": "string"},
{"id": "country", "title": "Country", "type": "string"},
{"id": "year", "title": "Year", "type": "integer"},
{"id": "language", "title": "Languages", "type": "string"},
{"id": "license", "title": "License", "type": "string"},
{"id": "places", "title": "Places", "type": "string"},
{"id": "events", "title": "Events", "type": "string"},
{"id": "featuring", "title": "Featuring", "type": "string"},
{"id": "keywords", "title": "Keywords", "type": "string"}
],
/*
@ -120,41 +117,9 @@
"sort": true,
"sortType": "title"
},
{
"id": "source",
"title": "Source",
"type": "string",
"autocomplete": true,
"description": true,
"columnWidth": 180,
"filter": true,
"find": true,
"sort": true
},
{
"id": "project",
"title": "Project",
"type": "string",
"autocomplete": true,
"description": true,
"columnWidth": 120,
"filter": true,
"find": true,
"sort": true
},
{
"id": "topic",
"title": "Topic",
"type": ["string"],
"autocomplete": true,
"columnWidth": 180,
"filter": true,
"find": true,
"sort": true
},
{
"id": "name",
"title": "People",
"title": "Name",
"type": ["string"],
"autocomplete": true,
"find": true
@ -169,15 +134,6 @@
"sort": true,
"sortType": "person"
},
{
"id": "cinematographer",
"title": "Cinematographer",
"type": ["string"],
"autocomplete": true,
"columnWidth": 180,
"sort": true,
"sortType": "person"
},
{
"id": "featuring",
"title": "Featuring",
@ -200,8 +156,8 @@
"sort": true
},
{
"id": "location",
"title": "Location",
"id": "country",
"title": "Contry",
"type": "string",
"autocomplete": true,
"columnWidth": 180,
@ -210,11 +166,14 @@
"sort": true
},
{
"id": "date",
"title": "Date",
"type": "string",
"columnWidth": 120,
//"format": {"type": "date", "args": ["%a, %b %e, %Y"]},
"id": "year",
"title": "Year",
"type": "year",
"additionalSort": [{"key": "director", "operator": "+"}, {"key": "title", "operator": "+"}],
"autocomplete": true,
"columnWidth": 60,
"filter": true,
"find": true,
"sort": true
},
{
@ -230,24 +189,6 @@
"columnWidth": 90,
"sort": true
},
{
"id": "annotations",
"title": "Annotations",
"type": "string",
"find": true
},
{
"id": "places",
"title": "Places",
"type": "layer",
"find": true
},
{
"id": "events",
"title": "Events",
"type": "layer",
"find": true
},
{
"id": "keywords",
"title": "Keywords",
@ -255,14 +196,14 @@
"find": true
},
{
"id": "descriptions",
"title": "Descriptions",
"id": "subtitles",
"title": "Subtitles",
"type": "layer",
"find": true
},
{
"id": "transcripts",
"title": "Transcripts",
"id": "publicnotes",
"title": "Notes",
"type": "layer",
"find": true
},
@ -405,14 +346,7 @@
"title": "User",
"type": "string",
"capability": "canSeeFiles",
"find": true
},
{
"id": "filename",
"title": "Filename",
"type": ["string"],
"capability": "canSeeFiles",
"find": true
"find": false
},
{
"id": "created",
@ -448,14 +382,6 @@
"format": {"type": "date", "args": ["%Y-%m-%d %H:%M:%S"]},
"sort": true
},
{
"id": "license",
"title": "License",
"type": ["string"],
"columnWidth": 120,
"filter": true,
"sort": true
},
{
"id": "rightslevel",
"title": "Rights Level",
@ -492,43 +418,44 @@
],
"layers": [
{
"id": "places",
"title": "Places",
"id": "privatenotes",
"title": "Private Notes",
"canAddAnnotations": {"member": true, "staff": true, "admin": true},
"item": "Place",
"item": "Note",
"overlap": true,
"type": "place"
"private": true,
"showInfo": true,
"type": "text"
},
{
"id": "events",
"title": "Events",
"id": "publicnotes",
"title": "Notes",
"canAddAnnotations": {"member": true, "staff": true, "admin": true},
"item": "Event",
"hasEvents": true,
"hasPlaces": true,
"item": "Note",
"overlap": true,
"type": "event"
"showInfo": true,
"type": "text"
},
{
"id": "keywords",
"title": "Keywords",
"canAddAnnotations": {"member": true, "staff": true, "admin": true},
"hasEvents": true,
"hasPlaces": true,
"item": "Keyword",
"overlap": true,
"type": "string"
},
{
"id": "descriptions",
"title": "Descriptions",
"canAddAnnotations": {"member": true, "staff": true, "admin": true},
"item": "Description",
"showInfo": true,
"type": "text"
},
{
"id": "transcripts",
"title": "Transcripts",
"canAddAnnotations": {"member": true, "staff": true, "admin": true},
"item": "Transcript",
"showInfo": true,
"id": "subtitles",
"title": "Subtitles",
"canAddAnnotations": {"staff": true, "admin": true},
"hasEvents": true,
"hasPlaces": true,
"isSubtitles": true,
"item": "Subtitle",
"type": "text"
}
],
@ -570,7 +497,7 @@
"system": "system@pandora.local"
},
"id": "pandora",
"name": "pan.do/ra",
"name": "Demo",
"url": "pandora.local",
"videoprefix": ""
},
@ -605,34 +532,33 @@
"annotationsCalendarSize": 128,
"annotationsFont": "small",
"annotationsMapSize": 128,
"annotationsRange": "position",
"annotationsRange": "all",
"annotationsSize": 256,
"annotationsSort": "position",
"clipsColumns": 2,
"columns": {
"Colors": {
"columns": ["title", "source", "project", "language", "hue", "saturation", "brightness"],
"columns": ["title", "director", "language", "hue", "saturation", "brightness"],
"columnWidth": {}
}
},
"filters": [
{"id": "source", "sort": [{"key": "name", "operator": "+"}]},
{"id": "project", "sort": [{"key": "name", "operator": "+"}]},
{"id": "topic", "sort": [{"key": "items", "operator": "-"}]},
{"id": "name", "sort": [{"key": "items", "operator": "-"}]},
{"id": "keywords", "sort": [{"key": "items", "operator": "-"}]},
{"id": "places", "sort": [{"key": "items", "operator": "-"}]}
{"id": "director", "sort": [{"key": "items", "operator": "-"}]},
{"id": "country", "sort": [{"key": "items", "operator": "-"}]},
{"id": "year", "sort": [{"key": "name", "operator": "+"}]},
{"id": "featuring", "sort": [{"key": "items", "operator": "-"}]},
{"id": "keywords", "sort": [{"key": "items", "operator": "-"}]}
],
"filtersSize": 176,
"find": {"conditions": [], "operator": "&"},
"followPlayer": true,
"icons": "frames",
"icons": "posters",
"infoIconSize": 256,
"item": "",
"itemFind": "",
"itemSort": [{"key": "position", "operator": "+"}],
"itemView": "info",
"listColumns": ["title", "source", "project", "topic", "language", "duration"],
"listColumns": ["title", "director", "year", "language", "duration"],
"listColumnWidth": {},
"listSelection": [],
"listSort": [{"key": "title", "operator": "+"}],
@ -655,11 +581,10 @@
"showIconBrowser": false,
"showInfo": true,
"showLayers": {
"places": false,
"events": false,
"keywords": true,
"descriptions": true,
"transcripts": true
"privatenotes": true,
"publicnotes": true,
"subtitles": true
},
"showMapControls": false,
"showMapLabels": false,

View file

@ -34,7 +34,7 @@ class Command(BaseCommand):
for f in models.ItemSort._meta.fields:
if not f.primary_key:
name = f.name
col_type = f.db_type()
col_type = f.db_type(connection)
if name not in db_fields:
sql = 'ALTER TABLE "%s" ADD COLUMN "%s" %s' % (table_name, name, col_type)
changes.append(sql)

View file

@ -314,7 +314,10 @@ class Item(models.Model):
#this does not work if another item without imdbid has the same metadata
oxdbId = self.oxdb_id()
if oxdbId:
if not settings.USE_IMDB:
update_poster = self.oxdbId != oxdbId
self.oxdbId = oxdbId
elif oxdbId:
if self.oxdbId != oxdbId:
q = Item.objects.filter(oxdbId=oxdbId).exclude(id=self.id)
if q.count() != 0:
@ -554,10 +557,8 @@ class Item(models.Model):
return i
def oxdb_id(self):
if not settings.USE_IMDB:
return self.itemId
if not self.get('title') and not self.get('director'):
return None
return self.itemId
return ox.get_oxid(self.get('seriesTitle', self.get('title', '')),
self.get('director', []),
self.get('seriesYear', self.get('year', '')),
@ -1128,13 +1129,10 @@ class Item(models.Model):
cmd += [
'-l', timeline,
]
if settings.USE_IMDB:
if len(self.itemId) == 7:
cmd += ['-i', self.itemId]
oxdbId = self.oxdbId or self.oxdb_id() or self.itemId
cmd += ['-o', oxdbId]
else:
cmd += ['-i', self.itemId]
cmd += [
'-i', self.itemId,
'-o', self.oxdbId or self.oxdb_id() or self.itemId
]
ox.makedirs(os.path.join(settings.MEDIA_ROOT,self.path()))
p = subprocess.Popen(cmd)
p.wait()

View file

@ -129,7 +129,7 @@ def render_poster(title, director, year, series, oxdb_id, imdb_id, frame, timeli
def main():
parser = OptionParser()
parser.add_option('-o', '--oxdbid', dest='oxdb_id', help='0xDB Id')
parser.add_option('-i', '--id', dest='imdb_id', help='Item Id')
parser.add_option('-i', '--id', dest='item_id', help='Item Id')
parser.add_option('-t', '--title', dest='title', help='Title')
parser.add_option('-d', '--director', dest='director', help='Director(s)', default='')
parser.add_option('-y', '--year', dest='year', help='Year')
@ -144,7 +144,7 @@ def main():
sys.exit()
opt = {}
for key in ('oxdb_id', 'imdb_id', 'title', 'director', 'year', 'series', 'frame', 'timeline', 'poster'):
for key in ('oxdb_id', 'item_id', 'title', 'director', 'year', 'series', 'frame', 'timeline', 'poster'):
opt[key] = getattr(options, key)
opt['title'] = opt['title'].decode('utf-8')

View file

@ -16,68 +16,140 @@ from optparse import OptionParser
from ox.image import drawText, wrapText
import sys
static_root = os.path.join(os.path.dirname(__file__), 'data')
def render_poster(id, title, frame, timeline, poster):
def render_poster(title, director, year, series, oxdb_id, imdb_id, frame, timeline, poster):
def get_oxdb_color(oxdb_id, series=False):
i = int(round((int(oxdb_id[2:10], 16) * 762 / pow(2, 32))))
if i < 127:
color = (127, i, 0)
elif i < 254:
color = (254 - i, 127, 0)
elif i < 381:
color = (0, 127, i - 254)
elif i < 508:
color = (0, 508 - i, 127)
elif i < 635:
color = (i - 508, 0, 127)
else:
color = (127, 0, 762 - i)
if series:
color = tuple(map(lambda x: x + 128, color))
return color
poster_width = 640
poster_height = 1024
poster_ratio = poster_width / poster_height
poster_color = (255, 255, 0)
poster_image = Image.new('RGB', (poster_width, poster_height))
draw = ImageDraw.Draw(poster_image)
font_file = os.path.join(static_root, 'DejaVuSansCondensedBold.ttf')
font_size = 48
font_size = {
'small': 28,
'large': 42,
}
# frame
frame_width = poster_width
frame_ratio = 4 / 3
frame_height = int(round(frame_width / frame_ratio))
if frame:
frame_image = Image.open(frame)
frame_image_ratio = frame_image.size[0] / frame_image.size[1]
if frame_ratio < frame_image_ratio:
frame_image = frame_image.resize((int(frame_height * frame_image_ratio), frame_height), Image.ANTIALIAS)
left = int((frame_image.size[0] - frame_width) / 2)
frame_image = frame_image.crop((left, 0, left + frame_width, frame_height))
else:
frame_image = frame_image.resize((frame_width, int(frame_width / frame_image_ratio)), Image.ANTIALIAS)
top = int((frame_image.size[1] - frame_height) / 2)
frame_image = frame_image.crop((0, top, frame_width, top + frame_height))
poster_image.paste(frame_image, (0, 0))
# timeline
timeline_width = poster_width
timeline_height = 64
timeline_lines = 16
if timeline:
timeline_image = Image.open(timeline)
timeline_image = timeline_image.resize((10240, timeline_height), Image.ANTIALIAS)
for i in range(timeline_lines):
line_image = timeline_image.crop((i * poster_width, 0, (i + 1) * poster_width, 64))
poster_image.paste(line_image, (0, i * timeline_height))
timeline_image = timeline_image.resize((timeline_width, timeline_height), Image.ANTIALIAS)
poster_image.paste(timeline_image, (0, frame_height))
# id
text = '' + id
text_image = Image.new('RGB', (1, 1))
text_size = drawText(text_image, (0, 0), text, font_file, font_size, poster_color)
# text
text_width = poster_width
text_height = timeline_height
text_left = int((poster_width - text_width) / 2)
text_top = 14 * timeline_height
for y in range(text_top, text_top + text_height):
for x in range(text_left, text_left + text_width):
if y < text_top + 4 or y >= text_top + text_height - 4:
poster_image.putpixel((x, y), poster_color)
text_height = poster_height - frame_height - timeline_height
text_top = frame_height + timeline_height
text_bottom = text_top + text_height
text_margin = 16
text_color = get_oxdb_color(oxdb_id, series)
font_color = tuple(map(lambda x: x - 128 if series else x + 128, text_color))
draw.rectangle([(0, text_top), (text_width, text_bottom)], fill=text_color)
offset_top = text_top + text_margin
if not director:
title_max_lines = 7
else:
title_max_lines = min(len(wrapText(title, text_width - 2 * text_margin, 0, font_file, font_size['large'])), 6)
director_max_lines = 9 - int((title_max_lines * 3 - 1) / 2)
if director:
lines = wrapText(director, text_width - 2 * text_margin, director_max_lines, font_file, font_size['small'])
for i, line in enumerate(lines):
size = drawText(poster_image, (text_margin, offset_top), line, font_file, font_size['small'], font_color)
offset_top += font_size['small'] + 2
offset_top += size[1] - font_size['small'] + text_margin / 2
lines = wrapText(title, text_width - 2 * text_margin, title_max_lines, font_file, font_size['large'])
for i, line in enumerate(lines):
size = drawText(poster_image, (text_margin, offset_top + 5), line, font_file, font_size['large'], font_color)
offset_top += font_size['large'] + 3
offset_top += size[1] - font_size['small'] + text_margin / 2
if year:
drawText(poster_image, (text_margin, offset_top), year, font_file, font_size['small'], font_color)
item_id = imdb_id or oxdb_id
drawText(poster_image, (text_margin, text_bottom - text_margin - font_size['large'] + 2), item_id, font_file, font_size['large'], font_color)
'''
# logo
logo_height = 32
logo_image = Image.open(os.path.join(static_root, '..', '..', 'static', 'png', 'logo.png'))
logo_width = int(round(logo_height * logo_image.size[0] / logo_image.size[1]))
logo_image = logo_image.resize((logo_width, logo_height), Image.ANTIALIAS)
logo_left = text_width - text_margin - logo_width
logo_top = text_bottom - text_margin - logo_height
for y in range(logo_height):
for x in range(logo_width):
poster_color = poster_image.getpixel((logo_left + x, logo_top + y))
logo_color = logo_image.getpixel((x, y))[0]
alpha = logo_image.getpixel((x, y))[3]
if series:
poster_color = tuple(map(lambda x: int(x - (logo_color - 16) * alpha / 255), poster_color))
else:
pixel = list(poster_image.getpixel((x, y)))
for c in range(3):
pixel[c] = int((pixel[c] + poster_color[c]) / 4)
poster_image.putpixel((x, y), tuple(pixel))
drawText(poster_image, ((poster_width - text_size[0]) / 2, text_top + (text_height - text_size[1]) / 2), text, font_file, font_size, poster_color)
poster_color = tuple(map(lambda x: int(x + (logo_color - 16) * alpha / 255), poster_color))
poster_image.putpixel((logo_left + x, logo_top + y), poster_color)
i '''
poster_image.save(poster)
def main():
parser = OptionParser()
parser.add_option('-o', '--oxdbid', dest='oxdb_id', help='0xDB Id')
parser.add_option('-i', '--id', dest='id', help='Item Id')
parser.add_option('-t', '--title', dest='title', help='Title', default='')
parser.add_option('-d', '--director', dest='director', help='Director', default='')
parser.add_option('-y', '--year', dest='year', help='Year', default='')
parser.add_option('-i', '--id', dest='imdb_id', help='Item Id')
parser.add_option('-t', '--title', dest='title', help='Title')
parser.add_option('-d', '--director', dest='director', help='Director(s)', default='')
parser.add_option('-y', '--year', dest='year', help='Year')
parser.add_option('-s', '--series', dest='series', help='Movie is an episode of a series', action='store_true')
parser.add_option('-f', '--frame', dest='frame', help='Poster frame (image file to be read)')
parser.add_option('-l', '--timeline', dest='timeline', help='Timeline (image file to be read)')
parser.add_option('-p', '--poster', dest='poster', help='Poster (image file to be written)')
(options, args) = parser.parse_args()
if options.oxdb_id and not options.id:
options.id = options.oxdb_id
if None in (options.id, options.poster):
if None in (options.oxdb_id, options.title, options.poster):
parser.print_help()
sys.exit()
opt = {}
for key in ('id', 'title', 'frame', 'timeline', 'poster'):
for key in ('oxdb_id', 'imdb_id', 'title', 'director', 'year', 'series', 'frame', 'timeline', 'poster'):
opt[key] = getattr(options, key)
opt['title'] = opt['title'].decode('utf-8')
opt['director'] = opt['director'].decode('utf-8')
render_poster(**opt)

View file

@ -133,77 +133,10 @@ pandora.ui.infoView = function(data) {
}
var listKeys = [
'language', 'topic', 'director', 'cinematographer', 'featuring',
'groups', 'license'
'country', 'language', 'director', 'featuring',
'groups'
];
// Source & Project --------------------------------------------------------
var count = 0;
['source', 'project'].forEach(function(key) {
$div = $('<div>').appendTo($data);
if (canEdit || data[key]) {
count && $('<br>').appendTo($div);
$('<div>')
.css({float: 'left'})
.html(
formatKey({
category: 'categories',
}[key] || key).replace('</span>', '&nbsp;</span>')
)
.appendTo($div);
Ox.Editable({
clickLink: pandora.clickLink,
format: function(value) {
return listKeys.indexOf(key) >= 0
? formatValue(value.split(', '), {
'director': 'name',
'cinematographer': 'name',
'features': 'name',
}[key] || key)
: value;
},
placeholder: formatLight('unknown'),
editable: canEdit,
tooltip: canEdit ? 'Doubleclick to edit' : '',
value: listKeys.indexOf(key) >= 0
? (data[key] || []).join(', ')
: data[key] || ''
})
.css({float: 'left'})
.bindEvent({
submit: function(event) {
editMetadata(key, event.value);
}
})
.appendTo($div);
if (canEdit || data[key + 'description']) {
$('<br>').css({'clear': 'both'}).appendTo($div);
$('<div>')
.append(
descriptions[key] = Ox.Editable({
clickLink: pandora.clickLink,
placeholder: formatLight('No ' + Ox.toTitleCase(key) + ' Description'),
editable: canEdit,
tooltip: canEdit ? 'Doubleclick to edit' : '',
type: 'textarea',
value: data[key + 'description'] || ''
})
.bindEvent({
submit: function(event) {
editMetadata(key + 'description', event.value);
}
})
.css(css)
).css({
'margin-top': '8px',
})
.appendTo($div);
}
count++;
}
});
// Title -------------------------------------------------------------------
$('<div>')
@ -232,11 +165,11 @@ pandora.ui.infoView = function(data) {
)
.appendTo($center);
// Location, Date, Language and Duration -----------------------------------
// Year, Country, Language and Duration -----------------------------------
if (canEdit) {
$div = $('<div>').css(css).css({marginTop: '12px'}).appendTo($center);
['location', 'date', 'language', 'duration'].forEach(function(key, i) {
['year', 'country', 'language', 'duration'].forEach(function(key, i) {
i && $('<div>').css({float: 'left'}).html(';&nbsp;').appendTo($div);
$('<div>')
.css({float: 'left'})
@ -266,7 +199,7 @@ pandora.ui.infoView = function(data) {
$('<br>').appendTo($center);
} else {
html = [];
['location', 'date', 'language', 'duration'].forEach(function(key) {
['year', 'country', 'language', 'duration'].forEach(function(key) {
if (data[key]) {
html.push(formatKey(key) + formatValue(data[key], key));
}
@ -278,7 +211,7 @@ pandora.ui.infoView = function(data) {
if (canEdit) {
$div = $('<div>').css(css).css('clear', 'both').appendTo($center);
['director', 'cinematographer', 'featuring'].forEach(function(key, i) {
['director', 'featuring'].forEach(function(key, i) {
i && $('<div>').css({float: 'left'}).html(';&nbsp;').appendTo($div);
$('<div>')
.css({float: 'left'})
@ -306,7 +239,7 @@ pandora.ui.infoView = function(data) {
$('<br>').appendTo($center);
} else if (data.director || data.cinematographer || data.featuring) {
html = [];
['director', 'cinematographer', 'featuring'].forEach(function(key) {
['director', 'featuring'].forEach(function(key) {
if (data[key] && data[key].length) {
html.push(
formatKey(key)
@ -317,40 +250,6 @@ pandora.ui.infoView = function(data) {
$('<div>').css(css).html(html.join('; ')).appendTo($center);
}
// Topic -------------------------------------------------------------------
if (canEdit) {
var key = 'topic';
$div = $('<div>').css(css).css('clear', 'both').appendTo($center);
$('<div>')
.css({float: 'left'})
.html(formatKey('Topics').replace('</span>', '&nbsp;</span>'))
.appendTo($div);
Ox.Editable({
clickLink: pandora.clickLink,
format: function(value) {
return formatValue(value.split(', '), key);
},
placeholder: formatLight('unknown'),
tooltip: 'Doubleclick to edit',
value: listKeys.indexOf(key) >= 0
? (data[key] || []).join(', ')
: data[key] || ''
})
.css({float: 'left'})
.bindEvent({
submit: function(event) {
editMetadata(key, event.value);
}
})
.appendTo($div);
$('<br>').appendTo($center);
} else if (data.topic) {
html = formatKey('topics') + formatValue(data.topic, 'topic');
$('<div>').css(css).html(html).appendTo($center);
}
// Summary -------------------------------------------------------------
if (canEdit) {
@ -379,32 +278,6 @@ pandora.ui.infoView = function(data) {
$('<div>').css(css).html(data.summary).appendTo($center);
}
// License -----------------------------------------------------------------
$div = $('<div>').css(css).css({marginTop: '16px'}).appendTo($center);
if (canEdit) {
$('<div>')
.css({float: 'left'})
.html(formatKey('license').replace('</span>', '&nbsp;</span>'))
.appendTo($div);
Ox.Editable({
placeholder: formatLight('No License'),
tooltip: 'Doubleclick to edit',
value: (data.license || []).join(', ')
})
.bindEvent({
submit: function(event) {
editMetadata('license', event.value);
}
})
.appendTo($div);
} else if (data.license) {
$div.html(
formatKey('License')
+ (data.license || []).join(', ')
);
}
// Hue, Saturation, Lightness, Volume --------------------------------------
['hue', 'saturation', 'lightness', 'volume'].forEach(function(key) {

View file

@ -38,7 +38,6 @@ DATABASES = {
}
BROKER_PASSWORD = "$RABBITPWD"
XACCELREDIRECT = True
DB_GIN_TRGM = True
DEBUG = False
TEMPLATE_DEBUG = DEBUG
@ -49,7 +48,7 @@ cd /srv/pandora/pandora
sudo -u pandora python manage.py syncdb --noinput
sudo -u pandora python manage.py sqlfindindex | sudo -u pandora python manage.py dbshell
echo "UPDATE django_site SET domain = '$HOST.local', name = '$HOST.local' WHERE 1=1;" | sudo -u pandora python manage.py dbshell
echo "DB_GIN_TRGM = True" >> /srv/pandora/pandora/local_settings.py
mkdir /srv/pandora/data
chown -R pandora:pandora /srv/pandora