From 06741903bab2da217dfedb4216449ef0a5f1bd5b Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Mon, 9 Jan 2012 14:36:35 +0530 Subject: [PATCH] output some metadata for search engines, cleanup padma metadata --- pandora/0xdb.jsonc | 1 + pandora/app/views.py | 3 +- pandora/item/views.py | 58 ++++++++++++++++++++++++++++- pandora/padma.jsonc | 48 +++++++++++++++--------- pandora/templates/index.html | 16 +++++++- pandora/templates/item.html | 47 +++++++++++++++++++++++ pandora/urls.py | 2 +- static/js/pandora/infoView.padma.js | 35 ++--------------- 8 files changed, 158 insertions(+), 52 deletions(-) create mode 100644 pandora/templates/item.html diff --git a/pandora/0xdb.jsonc b/pandora/0xdb.jsonc index 96413135..1d210b6b 100644 --- a/pandora/0xdb.jsonc +++ b/pandora/0xdb.jsonc @@ -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) diff --git a/pandora/app/views.py b/pandora/app/views.py index 077a8066..a26898ae 100644 --- a/pandora/app/views.py +++ b/pandora/app/views.py @@ -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) diff --git a/pandora/item/views.py b/pandora/item/views.py index adca932f..d9e7cef5 100644 --- a/pandora/item/views.py +++ b/pandora/item/views.py @@ -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': '
\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) + diff --git a/pandora/padma.jsonc b/pandora/padma.jsonc index 37f52dfc..be8ca61d 100644 --- a/pandora/padma.jsonc +++ b/pandora/padma.jsonc @@ -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": "+"}], diff --git a/pandora/templates/index.html b/pandora/templates/index.html index e2d23ebf..82b40977 100644 --- a/pandora/templates/index.html +++ b/pandora/templates/index.html @@ -15,6 +15,20 @@ + + + + + + + + - + + + diff --git a/pandora/templates/item.html b/pandora/templates/item.html new file mode 100644 index 00000000..9bb3118e --- /dev/null +++ b/pandora/templates/item.html @@ -0,0 +1,47 @@ + + + + + {{settings.SITENAME}} - {{title}} + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pandora/urls.py b/pandora/urls.py index 6f1a06c1..4957b75c 100644 --- a/pandora/urls.py +++ b/pandora/urls.py @@ -46,7 +46,7 @@ urlpatterns += patterns('', ) urlpatterns += patterns('', (r'^(?P[A-Z0-9].+)/embed', 'app.views.embed'), - (r'^[A-Z0-9].*$', 'app.views.index'), + (r'^(?P[A-Z0-9].*)$', 'item.views.item'), (r'^[a-z0-9].+$', 'app.views.index'), (r'^$', 'app.views.index'), (r'^.*$', 'app.views.index'), diff --git a/static/js/pandora/infoView.padma.js b/static/js/pandora/infoView.padma.js index 58dea2d1..dd705396 100644 --- a/static/js/pandora/infoView.padma.js +++ b/static/js/pandora/infoView.padma.js @@ -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']; $('
').html('
').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 '' + 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 ? @@ -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?