Compare commits

...

4 commits

Author SHA1 Message Date
j
85095eda44 only use current search if its inside a layer 2019-11-01 15:22:53 +01:00
j
ae2e3e45c6 download parts and source 2019-10-31 11:16:16 +01:00
j
6af2a1cbe6 default to list of countries 2019-10-31 11:10:29 +01:00
j
53c9d13aa7 list bionic 2019-10-31 11:10:14 +01:00
11 changed files with 96 additions and 21 deletions

View file

@ -38,6 +38,7 @@
"canAddItems": {"staff": true, "admin": true}, "canAddItems": {"staff": true, "admin": true},
"canAddDocuments": {"staff": true, "admin": true}, "canAddDocuments": {"staff": true, "admin": true},
"canDownloadVideo": {"guest": -1, "member": -1, "friend": -1, "staff": -1, "admin": -1}, "canDownloadVideo": {"guest": -1, "member": -1, "friend": -1, "staff": -1, "admin": -1},
"canDownloadSource": {"guest": -1, "member": -1, "friend": -1, "staff": -1, "admin": -1},
"canEditAnnotations": {"staff": true, "admin": true}, "canEditAnnotations": {"staff": true, "admin": true},
"canEditEntities": {"staff": true, "admin": true}, "canEditEntities": {"staff": true, "admin": true},
"canEditDocuments": {"staff": true, "admin": true}, "canEditDocuments": {"staff": true, "admin": true},

View file

@ -39,6 +39,7 @@
"canAddItems": {"researcher": true, "staff": true, "admin": true}, "canAddItems": {"researcher": true, "staff": true, "admin": true},
"canAddDocuments": {"researcher": true, "staff": true, "admin": true}, "canAddDocuments": {"researcher": true, "staff": true, "admin": true},
"canDownloadVideo": {"guest": -1, "member": -1, "researcher": 3, "staff": 3, "admin": 3}, "canDownloadVideo": {"guest": -1, "member": -1, "researcher": 3, "staff": 3, "admin": 3},
"canDownloadSource": {"guest": -1, "member": -1, "researcher": -1, "staff": -1, "admin": -1},
"canEditAnnotations": {"staff": true, "admin": true}, "canEditAnnotations": {"staff": true, "admin": true},
"canEditDocuments": {"researcher": true, "staff": true, "admin": true}, "canEditDocuments": {"researcher": true, "staff": true, "admin": true},
"canEditEntities": {"staff": true, "admin": true}, "canEditEntities": {"staff": true, "admin": true},

View file

@ -38,6 +38,7 @@
"canAddItems": {"member": true, "staff": true, "admin": true}, "canAddItems": {"member": true, "staff": true, "admin": true},
"canAddDocuments": {"member": true, "staff": true, "admin": true}, "canAddDocuments": {"member": true, "staff": true, "admin": true},
"canDownloadVideo": {"guest": 0, "member": 0, "staff": 4, "admin": 4}, "canDownloadVideo": {"guest": 0, "member": 0, "staff": 4, "admin": 4},
"canDownloadSource": {"guest": -1, "member": -1, "staff": 4, "admin": 4},
"canEditAnnotations": {"staff": true, "admin": true}, "canEditAnnotations": {"staff": true, "admin": true},
"canEditEntities": {"staff": true, "admin": true}, "canEditEntities": {"staff": true, "admin": true},
"canEditDocuments": {"staff": true, "admin": true}, "canEditDocuments": {"staff": true, "admin": true},

View file

@ -45,6 +45,7 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution.
"canAddItems": {"member": true, "staff": true, "admin": true}, "canAddItems": {"member": true, "staff": true, "admin": true},
"canAddDocuments": {"member": true, "staff": true, "admin": true}, "canAddDocuments": {"member": true, "staff": true, "admin": true},
"canDownloadVideo": {"guest": 1, "member": 1, "staff": 4, "admin": 4}, "canDownloadVideo": {"guest": 1, "member": 1, "staff": 4, "admin": 4},
"canDownloadSource": {"member": 1, "staff": 4, "admin": 4},
"canEditAnnotations": {"staff": true, "admin": true}, "canEditAnnotations": {"staff": true, "admin": true},
"canEditDocuments": {"staff": true, "admin": true}, "canEditDocuments": {"staff": true, "admin": true},
"canEditEntities": {"staff": true, "admin": true}, "canEditEntities": {"staff": true, "admin": true},
@ -550,7 +551,7 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution.
{ {
"id": "country", "id": "country",
"title": "Country", "title": "Country",
"type": "string", "type": ["string"],
"autocomplete": true, "autocomplete": true,
"columnWidth": 180, "columnWidth": 180,
"filter": true, "filter": true,

View file

@ -639,6 +639,9 @@ class Item(models.Model):
if self.poster_height: if self.poster_height:
i['posterRatio'] = self.poster_width / self.poster_height i['posterRatio'] = self.poster_width / self.poster_height
if 'source' in keys:
i['source'] = self.files.filter(selected=True).exclude(data='').exists()
streams = self.streams() streams = self.streams()
i['durations'] = [s.duration for s in streams] i['durations'] = [s.duration for s in streams]
i['duration'] = sum(i['durations']) i['duration'] = sum(i['durations'])

View file

@ -16,6 +16,7 @@ urlpatterns = [
url(r'^(?P<id>[A-Z0-9].*)/download$', views.download), url(r'^(?P<id>[A-Z0-9].*)/download$', views.download),
url(r'^(?P<id>[A-Z0-9].*)/download/$', views.download), url(r'^(?P<id>[A-Z0-9].*)/download/$', views.download),
url(r'^(?P<id>[A-Z0-9].*)/download/source/(?P<part>\d+)?$', views.download_source), url(r'^(?P<id>[A-Z0-9].*)/download/source/(?P<part>\d+)?$', views.download_source),
url(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p(?P<part>\d+)\.(?P<format>webm|ogv|mp4)$', views.download),
url(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p\.(?P<format>webm|ogv|mp4)$', views.download), url(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p\.(?P<format>webm|ogv|mp4)$', views.download),
#video #video

View file

@ -992,6 +992,8 @@ def download_source(request, id, part=None):
raise Http404 raise Http404
parts = ['%s - %s ' % (item.get('title'), settings.SITENAME), item.public_id] parts = ['%s - %s ' % (item.get('title'), settings.SITENAME), item.public_id]
if len(streams) > 1:
parts.append('.Part %d' % (part + 1))
parts.append('.') parts.append('.')
parts.append(f.extension) parts.append(f.extension)
filename = ''.join(parts) filename = ''.join(parts)
@ -1002,7 +1004,7 @@ def download_source(request, id, part=None):
response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8')) response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8'))
return response return response
def download(request, id, resolution=None, format='webm'): def download(request, id, resolution=None, format='webm', part=None):
item = get_object_or_404(models.Item, public_id=id) item = get_object_or_404(models.Item, public_id=id)
if not resolution or int(resolution) not in settings.CONFIG['video']['resolutions']: if not resolution or int(resolution) not in settings.CONFIG['video']['resolutions']:
resolution = max(settings.CONFIG['video']['resolutions']) resolution = max(settings.CONFIG['video']['resolutions'])
@ -1010,22 +1012,35 @@ def download(request, id, resolution=None, format='webm'):
resolution = int(resolution) resolution = int(resolution)
if not item.access(request.user) or not item.rendered: if not item.access(request.user) or not item.rendered:
return HttpResponseForbidden() return HttpResponseForbidden()
if part is not None:
part = int(part) - 1
streams = item.streams()
if part > len(streams):
raise Http404
ext = '.%s' % format ext = '.%s' % format
parts = ['%s - %s ' % (item.get('title'), settings.SITENAME), item.public_id] parts = ['%s - %s ' % (item.get('title'), settings.SITENAME), item.public_id]
if resolution != max(settings.CONFIG['video']['resolutions']): if resolution != max(settings.CONFIG['video']['resolutions']):
parts.append('.%dp' % resolution) parts.append('.%dp' % resolution)
if part is not None:
parts.append('.Part %d' % (part + 1))
parts.append(ext) parts.append(ext)
filename = ''.join(parts) filename = ''.join(parts)
video = NamedTemporaryFile(suffix=ext) video = NamedTemporaryFile(suffix=ext)
content_type = mimetypes.guess_type(video.name)[0] content_type = mimetypes.guess_type(video.name)[0]
r = item.merge_streams(video.name, resolution, format) if part is None:
if not r: r = item.merge_streams(video.name, resolution, format)
return HttpResponseForbidden() if not r:
elif r is True: return HttpResponseForbidden()
response = HttpResponse(FileWrapper(video), content_type=content_type) elif r is True:
response['Content-Length'] = os.path.getsize(video.name) response = HttpResponse(FileWrapper(video), content_type=content_type)
response['Content-Length'] = os.path.getsize(video.name)
else:
response = HttpFileResponse(r, content_type=content_type)
else: else:
response = HttpFileResponse(r, content_type=content_type) stream = streams[part].get(resolution, format)
path = stream.media.path
content_type = mimetypes.guess_type(path)[0]
response = HttpFileResponse(path, content_type=content_type)
response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8')) response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8'))
return response return response

View file

@ -9,6 +9,10 @@ pandora.ui.downloadVideoDialog = function(options) {
'mp4': 'MP4', 'mp4': 'MP4',
}, },
parts = Ox.max(options.video.map(function(video) {
return video.index
})),
$content = Ox.Element() $content = Ox.Element()
.css({margin: '16px'}), .css({margin: '16px'}),
@ -27,6 +31,9 @@ pandora.ui.downloadVideoDialog = function(options) {
.css({marginBottom: '16px'}) .css({marginBottom: '16px'})
.appendTo($content), .appendTo($content),
$format,
$resolution,
$form = window.$form = Ox.Form({ $form = window.$form = Ox.Form({
items: [ items: [
Ox.Select({ Ox.Select({
@ -36,7 +43,10 @@ pandora.ui.downloadVideoDialog = function(options) {
id: format, id: format,
title: formats[format] title: formats[format]
}; };
}), }).concat(!options.out && options.source ? [{
id: 'source',
title: Ox._('Source')
}] : []),
label: Ox._('Format'), label: Ox._('Format'),
labelWidth: 120, labelWidth: 120,
value: pandora.site.video.downloadFormat, value: pandora.site.video.downloadFormat,
@ -44,9 +54,14 @@ pandora.ui.downloadVideoDialog = function(options) {
}) })
.bindEvent({ .bindEvent({
change: function(data) { change: function(data) {
if (data.value == 'source') {
$resolution.hide()
} else {
$resolution.show()
}
} }
}), }),
Ox.Select({ $resolution = Ox.Select({
id: 'resolution', id: 'resolution',
items: pandora.site.video.resolutions.map(function(resolution) { items: pandora.site.video.resolutions.map(function(resolution) {
return { return {
@ -63,7 +78,25 @@ pandora.ui.downloadVideoDialog = function(options) {
change: function(data) { change: function(data) {
} }
}) })
] ].concat(parts ? [
Ox.Select({
id: 'part',
items: Ox.range(parts + 1).map(function(resolution, idx) {
return {
id: idx + 1,
title: 'Part ' + (idx+1)
};
}),
label: Ox._('Part'),
labelWidth: 120,
value: 1,
width: 240
})
.bindEvent({
change: function(data) {
}
})
] : [])
}).appendTo($content), }).appendTo($content),
failed = false, failed = false,
@ -116,9 +149,17 @@ pandora.ui.downloadVideoDialog = function(options) {
}) })
} else { } else {
url = '/' + options.item if (values.format == 'source') {
+ '/download/' + values.resolution url = '/' + options.item
+ 'p.' + values.format + '/download/source/'
+ (values.part ? values.part : '')
} else {
url = '/' + options.item
+ '/download/' + values.resolution
+ 'p'
+ (values.part ? values.part : '')
+ '.' + values.format
}
} }
if (url) { if (url) {
that.close(); that.close();

View file

@ -28,7 +28,7 @@ pandora.ui.editor = function(data) {
enableSetPosterFrame: !pandora.site.media.importFrames && data.editable, enableSetPosterFrame: !pandora.site.media.importFrames && data.editable,
enableSubtitles: ui.videoSubtitles, enableSubtitles: ui.videoSubtitles,
find: ui.itemFind, find: ui.itemFind,
findLayer: ui._findState.key, findLayer: pandora.getFindLayer(),
getFrameURL: function(position) { getFrameURL: function(position) {
return pandora.getMediaURL('/' + ui.item + '/' + ui.videoResolution + 'p' + position + '.jpg?' + data.modified); return pandora.getMediaURL('/' + ui.item + '/' + ui.videoResolution + 'p' + position + '.jpg?' + data.modified);
}, },
@ -189,7 +189,9 @@ pandora.ui.editor = function(data) {
pandora.ui.downloadVideoDialog({ pandora.ui.downloadVideoDialog({
item: ui.item, item: ui.item,
rightsLevel: rightsLevel, rightsLevel: rightsLevel,
title: data.title source: data.source && pandora.hasCapability('canDownloadSource'),
title: data.title,
video: data.video
}).open(); }).open();
}, },
downloadselection: function(selection) { downloadselection: function(selection) {

View file

@ -1439,6 +1439,14 @@ pandora.getFoldersWidth = function(section) {
return width; return width;
}; };
pandora.getFindLayer = function() {
var key = pandora.user.ui._findState.key
if (!!Ox.getObjectById(pandora.site.layers, key)) {
key = 'all'
}
return key
};
pandora.getHash = function(state, callback) { pandora.getHash = function(state, callback) {
// FIXME: remove this // FIXME: remove this
var embedKeys = [ var embedKeys = [
@ -2359,6 +2367,7 @@ pandora.VIDEO_OPTIONS_KEYS = [
'rendered', 'rendered',
'rightslevel', 'rightslevel',
'size', 'size',
'source',
'streams', 'streams',
'title', 'title',
'videoRatio' 'videoRatio'

View file

@ -4,7 +4,7 @@
# Installing pan.do/ra inside LXC # Installing pan.do/ra inside LXC
1) Install lxc on the host (Ubuntu 16.04 or later): 1) Install lxc on the host (Ubuntu 18.04 or later):
sudo apt-get install lxc sudo apt-get install lxc
@ -15,7 +15,7 @@
2) Create a new container, use different names if installing multiple instances: 2) Create a new container, use different names if installing multiple instances:
sudo lxc-create -n pandora -t ubuntu -- -r xenial sudo lxc-create -n pandora -t ubuntu-cloud -- -r bionic
or or
@ -28,12 +28,12 @@
4) Attach to container and install pan.do/ra 4) Attach to container and install pan.do/ra
sudo lxc-attach -n pandora --clear-env sudo lxc-attach -n pandora --clear-env
apt-get update -qq && apt-get upgrade -y
apt-get -y install curl ca-certificates
sed -i s/ubuntu/pandora/g /etc/passwd /etc/shadow /etc/group sed -i s/ubuntu/pandora/g /etc/passwd /etc/shadow /etc/group
mv /home/ubuntu /home/pandora mv /home/ubuntu /home/pandora
echo "pandora:pandora" | chpasswd echo "pandora:pandora" | chpasswd
echo PasswordAuthentication no >> /etc/ssh/sshd_config echo PasswordAuthentication no >> /etc/ssh/sshd_config
apt-get update -qq && apt-get upgrade -y
apt-get -y install curl ca-certificates
locale-gen en_US.UTF-8 locale-gen en_US.UTF-8
update-locale LANG=en_US.UTF-8 update-locale LANG=en_US.UTF-8
export LANG=en_US.UTF-8 export LANG=en_US.UTF-8