output some metadata for search engines, cleanup padma metadata

This commit is contained in:
j 2012-01-09 14:36:35 +05:30
parent d6b9929052
commit 06741903ba
8 changed files with 158 additions and 52 deletions

View File

@ -556,6 +556,7 @@
],
"sendReferrer": false,
"site": {
"description": "0xDB is an experimental - and to some degree imaginary - movie database. It is intended to help re-imagine the future of cinema on the internet, to push the boundaries of web applications, and to serve as a point of reference for individuals and institutions who are dealing with large collections of films.",
// FIXME: "from" and "to" would be more intuitive as keys here
"email": {
// E-mail address in contact form (to)

View File

@ -15,6 +15,7 @@ from django.http import HttpResponse
from ox.django.shortcuts import json_response, render_to_json_response
from ox.django.decorators import login_required_json
import ox
from ox.utils import json
import models
@ -31,7 +32,7 @@ def intro(request):
def index(request):
context = RequestContext(request, {
'base_url': request.build_absolute_uri('/'),
'settings': settings
'settings': settings,
})
return render_to_response('index.html', context)

View File

@ -8,8 +8,9 @@ import random
import Image
from django.db.models import Count, Sum, Max
from django.template import RequestContext
from django.http import HttpResponse, HttpResponseForbidden, Http404
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import get_object_or_404, redirect, render_to_response
from django.conf import settings
from ox.utils import json
@ -807,3 +808,58 @@ def random_annotation(request):
clip = item.annotations.all()[pos]
return redirect('/%s'% clip.public_id)
def item(request, id):
id = id.split('/')[0]
template = 'index.html'
qs = models.Item.objects.filter(itemId=id)
if qs.count() == 0:
context = RequestContext(request, {
'base_url': request.build_absolute_uri('/'),
'settings': settings
})
else:
item = qs[0]
template = 'item.html'
keys = [
'year',
'director',
'country',
'keywords',
'summary'
]
data = []
for key in keys:
value = item.get(key)
if value:
if isinstance(value, list):
value = value = u', '.join([unicode(v) for v in value])
data.append({'key': key.capitalize(), 'value': value})
clips = []
for c in item.clips.all():
clip = {
'in': c.start,
'annotations': '<br />\n'.join([a.value for a in c.annotations.all()])
}
clips.append(clip)
ctx = {
'base_url': request.build_absolute_uri('/'),
'url': request.build_absolute_uri('/%s' % id),
'id': id,
'settings': settings,
'data': data,
'clips': clips,
'icon': 'poster',
}
for key in ('title', 'description', 'keywords'):
value = item.get({
'description': 'summary' in keys and 'summary' or 'description'
}.get(key, key))
if isinstance(value, list):
value = value = ', '.join(value)
if value:
ctx[key] = ox.stripTags(value)
context = RequestContext(request, ctx)
return render_to_response(template, context)

View File

@ -44,15 +44,16 @@
],
// fixme: either this, or filter: true in itemKeys, but not both
"filters": [
{"id": "collection", "title": "Collection", "type": "string"},
{"id": "source", "title": "Source", "type": "string"},
{"id": "director", "title": "Director", "type": "string"},
{"id": "cinematographer", "title": "Cinematographer", "type": "string"},
{"id": "source", "title": "Sources", "type": "string"},
{"id": "project", "title": "Projects", "type": "string"},
{"id": "topics", "title": "Topics", "type": "string"},
{"id": "name", "title": "People", "type": "string"},
{"id": "keywords", "title": "Keywords", "type": "string"},
{"id": "language", "title": "Languages", "type": "string"},
{"id": "places", "title": "Places", "type": "string"},
{"id": "year", "title": "Year", "type": "integer"},
{"id": "language", "title": "Language", "type": "string"},
{"id": "category", "title": "Category", "type": "string"},
{"id": "keywords", "title": "Keyword", "type": "string"}
{"id": "year", "title": "Years", "type": "integer"},
{"id": "director", "title": "Directors", "type": "string"},
{"id": "cinematographer", "title": "Cinematographers", "type": "string"}
],
/*
An itemKey must have the following properties:
@ -114,6 +115,17 @@
"find": true,
"sort": "person"
},
{
"id": "features",
"title": "Features",
"type": ["string"],
"autocomplete": true,
"columnRequired": true,
"columnWidth": 180,
"filter": true,
"find": true,
"sort": "person"
},
{
"id": "name",
"title": "Name",
@ -122,8 +134,8 @@
"find": true
},
{
"id": "collection",
"title": "Collection",
"id": "project",
"title": "Project",
"type": "string",
"autocomplete": true,
"columnWidth": 120,
@ -165,8 +177,8 @@
"find": true
},
{
"id": "category",
"title": "Category",
"id": "topic",
"title": "Topic",
"type": ["string"],
"autocomplete": true,
"columnWidth": 180,
@ -432,7 +444,7 @@
{"id": "clips", "title": "with Clips"},
{"id": "timelines", "title": "with Timelines"},
{"id": "maps", "title": "with Maps"},
{"id": "calendars", "title": "with Calendars"},
//{"id": "calendars", "title": "with Calendars"},
{"id": "clip", "title": "as Clips"},
//{"id": "video", "title": "as Video"},
{"id": "map", "title": "on Map"},
@ -453,6 +465,7 @@
],
"sendReferrer": true,
"site": {
"description": "Pad.ma is an online archive of densely text-annotated video material, primarily footage and not finished films. The entire collection is searchable and viewable online, and is free to download for non-commercial use.",
"email": {
// E-mail address in contact form (to)
"contact": "pad.ma@pad.ma",
@ -496,14 +509,15 @@
"clipsColumns": 2,
"columns": {
"Colors": {
"columns": ["title", "director", "location", "collection", "hue", "saturation", "brightness"],
"columns": ["title", "director", "location", "source", "hue", "saturation", "brightness"],
"columnWidth": {}
}
},
"filters": [
{"id": "collection", "sort": [{"key": "name", "operator": "+"}]},
{"id": "source", "sort": [{"key": "name", "operator": "+"}]},
{"id": "category", "sort": [{"key": "items", "operator": "-"}]},
{"id": "project", "sort": [{"key": "name", "operator": "+"}]},
{"id": "topic", "sort": [{"key": "items", "operator": "-"}]},
{"id": "people", "sort": [{"key": "items", "operator": "-"}]},
{"id": "keywords", "sort": [{"key": "items", "operator": "-"}]},
{"id": "places", "sort": [{"key": "items", "operator": "-"}]}
],
@ -515,7 +529,7 @@
"itemFind": {"conditions": [], "operator": "&"},
"itemSort": [{"key": "position", "operator": "+"}],
"itemView": "info",
"listColumns": ["title", "director", "location", "collection", "language", "duration", "source"],
"listColumns": ["title", "director", "location", "source", "language", "duration", "source"],
"listColumnWidth": {},
"listSelection": [],
"listSort": [{"key": "title", "operator": "+"}],

View File

@ -15,6 +15,20 @@
</script>
<script type="text/javascript" src="/static/oxjs/build/Ox.js"></script>
<script type="text/javascript" src="/static/js/pandora.js"></script>
<meta name="title" content="{{title}}" />
<meta name="description" content="{{settings.CONFIG.site.description|safe}}"/>
<meta property="og:title" content="{{title}}"/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="{{base_url}}"/>
<meta property="og:image" content="{{base_url}}static/png/icon64.png"/>
<meta property="og:site_name" content="{{settings.SITENAME}}"/>
<meta property="og:description" content="{{settings.CONFIG.site.description|safe}}"/>
</head>
<body></body>
<body>
<noscript>
<h1>{{settings.SITENAME}}</h1>
<p>{{settings.CONFIG.site.description|safe}}</p>
<p>{{settings.SITENAME}} requires JavaScript</p>
</noscript>
</body>
</html>

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{{settings.SITENAME}} - {{title}}</title>
<link rel="shortcut icon" type="image/png" href="/static/png/icon16.png"/>
<link rel="icon" href="/static/png/icon64.png" sizes="32x32"/>
<link rel="icon" href="/static/png/icon64.png" sizes="48x48"/>
<meta name="application-name" content="{{settings.SITENAME}}"/>
<meta name="application-url" content="{{base_url}}"/>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="{{settings.SITENAME}}" />
<script>
if (localStorage && !localStorage['Ox.theme'])
localStorage['Ox.theme'] = '"{{settings.CONFIG.user.ui.theme}}"';
</script>
<script type="text/javascript" src="/static/oxjs/build/Ox.js"></script>
<script type="text/javascript" src="/static/js/pandora.js"></script>
<meta name="title" content="{{title}}" />
<meta name="description" content="{{description|safe}}"/>
<meta name="keywords" content="{{keywords|safe}}"/>
<meta content="{{url}}/{{icon}}128.jpg" name="thumbnail"/>
<meta content="{{url}}/{{icon}}128.jpg" name="image_src"/>
<meta property="og:title" content="{{title}}"/>
<meta property="og:type" content="movie"/>
<meta property="og:url" content="{{url}}"/>
<meta property="og:image" content="{{url}}/{{icon}}128.jpg"/>
<meta property="og:site_name" content="{{settings.SITENAME}}"/>
<meta property="og:description" content="{{description|safe}}"/>
</head>
<body>
<noscript>
<img src="/{{id}}/poster256.jpg" style="float: left; margin-right: 8px">
<h1>{{title}}</h1>
{% for i in data %}
<div>
<b>{{i.key}}</b>: {{i.value|safe}}
</div>
{% endfor %}
{% for c in clips %}
<div style="clear:both;padding-top: 4px">
<img src="/{{id}}/96p{{c.in}}.jpg" style="float: left; margin-right: 8px">
{{c.annotations|safe}}
</div>
{% endfor %}
</noscript>
</body>
</html>

View File

@ -46,7 +46,7 @@ urlpatterns += patterns('',
)
urlpatterns += patterns('',
(r'^(?P<id>[A-Z0-9].+)/embed', 'app.views.embed'),
(r'^[A-Z0-9].*$', 'app.views.index'),
(r'^(?P<id>[A-Z0-9].*)$', 'item.views.item'),
(r'^[a-z0-9].+$', 'app.views.index'),
(r'^$', 'app.views.index'),
(r'^.*$', 'app.views.index'),

View File

@ -146,9 +146,6 @@ pandora.ui.infoView = function(data) {
.append(
Ox.Editable({
editable: isEditable,
format: function(value) {
return formatTitle(value);
},
tooltip: isEditable ? 'Doubleclick to edit' : '',
value: data.title
})
@ -267,16 +264,17 @@ pandora.ui.infoView = function(data) {
)
.appendTo($text);
var list_keys = ['language', 'category', 'director', 'cinematographer'];
var list_keys = ['language', 'category', 'director', 'cinematographer', 'features'];
$('<div>').html('<br>').appendTo($text);
[
'date',
'location',
'director',
'cinematographer',
'features',
'language',
'source',
'collection',
'project',
'category',
'user',
].forEach(function(key) {
@ -388,7 +386,7 @@ pandora.ui.infoView = function(data) {
if (value != data[key]) {
var edit = {id: data.id};
if (key == 'title') {
Ox.extend(edit, parseTitle(value));
edit[key] = value;
} else if(['director', 'country', 'language', 'category'].indexOf(key) > -1) {
edit[key] = value ? value.split(', ') : [];
} else {
@ -420,17 +418,6 @@ pandora.ui.infoView = function(data) {
return '<span style="color: rgb(128, 128, 128)">' + str + '</span>';
}
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 ?
@ -448,20 +435,6 @@ pandora.ui.infoView = function(data) {
);
}
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?