Commit 221f28de authored by Merret Buurman's avatar Merret Buurman
Browse files

First version of cmip6 file landing page.

parent de49ab0f
from django.template import loader
import requests
import json
import xml.etree.ElementTree as ET
def get_html_string(request, prefix, suffix):
handle_list = ['21.14100/foo','21.14100/bar','21.14100/foobar']
template = loader.get_template('landingpage/cmip6.html')
context = {
'handle_list': handle_list,
}
handle_values, json_record = _get_handle_values(prefix+'/'+suffix)
agg_level = _extract_agg_level(handle_values)
context = _get_handle_info_depending_on_aggregation_level(agg_level, handle_values, json_record)
template = _get_template_depending_on_aggregation_level(agg_level)
return template.render(context, request)
def _get_template_depending_on_aggregation_level(aggregation_level):
if aggregation_level.lower() == 'file':
return loader.get_template('landingpage/cmip6_file.html')
elif aggregation_level.lower() == 'dataset':
return loader.get_template('landingpage/cmip6_dataset.html')
else:
return loader.get_template('landingpage/cmip6_fallback.html')
def _get_handle_values(handle):
resp = requests.get('https://hdl.handle.net/api/handles/'+handle)
# TODO Put URL in config
# TODO ONE DAY - MAKE THIS AJAX???
# StackOverflow
# http://stackoverflow.com/questions/7699796/how-do-you-get-django-to-make-a-restful-call
# My opinion is to get the client to make the requests where possible; making your webserver block for an external call isn't very scalable or nice in general. However, be aware that AJAX requests must be made to the same domain (you can't do cross domain AJAX requests without using iframes, jsonp, or other trickery).
# TODO USE PYHANDLE HERE TO CATCH ERRORS
entries = json.loads(resp.content)['values']
values_dict = dict(
handle=handle
)
for entry in entries:
key = str(entry['type'])
val = str(entry['data']['value'])
values_dict[key] = val
return values_dict, entries
def _get_handle_info_depending_on_aggregation_level(agg_level, values, json_record):
if agg_level.lower() == 'file':
return _get_handle_info_for_file(values, json_record)
elif agg_level.lower() == 'dataset':
return _get_handle_info_for_dataset(values, json_record)
else:
return _get_dict_generic(values, json_record)
def _extract_agg_level(values_dict):
return values_dict['AGGREGATION_LEVEL']
def _get_handle_info_for_file(values, json_record):
context = {}
if 'FILENAME' in values:
context['file_name'] = values['FILENAME']
if 'FILESIZE' in values:
context['file_size'] = values['FILESIZE']
if 'CHECKSUM' in values:
context['checksum'] = values['CHECKSUM']
if 'CHECKSUM_METHOD' in values:
context['checksum_method'] = values['CHECKSUM_METHOD']
if 'URL_ORIGINAL_DATA' in values:
field_string = values['URL_ORIGINAL_DATA']
list_of_originals = _extract_url_info_from_field(field_string)
context['urls_original'] = list_of_originals
if 'URL_REPLICAS' in values:
context['urls_replicas'] = values['URL_REPLICAS']
if 'IS_PART_OF' in values or 'PARENT' in values: # TODO remove 'PARENT'
if 'IS_PART_OF' in values:
parent_list = values['IS_PART_OF'].split(';')
context['parents_list'] = parent_list
infodict, any_replaced = _get_parent_info(parent_list)
context['parents_info'] = infodict
context['any_parent_replaced'] = any_replaced
elif 'PARENT' in values:
parent_list = values['PARENT'].split(';')
context['parents_list'] = parent_list
infodict, any_replaced = _get_parent_info(parent_list)
context['parents_info'] = infodict
context['any_parent_replaced'] = any_replaced
context['content'] = json_record
context['values'] = values
context['handle'] = values['handle']
# TODO add replicas
return context
def _extract_url_info_from_field(field_string):
field_xml = ET.fromstring(field_string)
list_of_originals = []
temp_url_list = []
locations = field_xml.findall('location')
for location in locations:
url = location.get('href')
if url not in temp_url_list:
temp_url_list.append(url)
list_of_originals.append(dict(
host=location.get('host'),
url=url
))
return list_of_originals
def _get_handle_info_for_dataset(values):
return {}
def _get_dict_generic(values):
return {}
def _get_parent_info(list_of_parent_handles):
list_of_parent_info = []
any_replaced = False
for handle in list_of_parent_handles:
# Gather info:
handle_values, temp = _get_handle_values(handle)
aggregation_level = handle_values['AGGREGATION_LEVEL'].lower()
drs_id = handle_values['DRS_ID']
vers_num = handle_values['VERSION_NUMBER']
replaced = False
if 'REPLACED_BY' in handle_values:
newer = handle_values['REPLACED_BY']
any_replaced = True
if not newer == handle:
replaced = True
# Assemble info:
info = dict(
handle = handle,
level = aggregation_level,
drs = drs_id,
version = vers_num,
replaced = replaced
)
list_of_parent_info.append(info)
return list_of_parent_info, any_replaced
......@@ -11,22 +11,27 @@ body {
}
h1,h2,h3,h4,h5,h6 {
margin: 0 0 .5em;
margin: 0 0 0em;
font-weight: 500;
line-height: 1.1;
}
h2 {margin:0 0 0.5em;}
h1 { font-size: 2.25em; } /* 36px */
h2 { font-size: 1.75em; } /* 28px */
h2 { font-size: 1em; } /* px */
h3 { font-size: 1.375em; } /* 22px */
h4 { font-size: 1.125em; } /* 18px */
h5 { font-size: 1em; } /* 16px */
h6 { font-size: .875em; } /* 14px */
h2 { font-weight: bold; }
p
{
line-height: 1.5;
padding: 1em 1.25em;
/*padding: 1em 1.25em;*/
}
blockquote
......@@ -47,12 +52,51 @@ hr
table
{
background-color: transparent;
background-color: #f8ffff; /*transparent*/ /*#f0f4f4*/ /*f0f8f8*/ /*#f0fcfc*/
border-spacing: 0;
border-collapse: collapse;
border-top: 1px solid #ddd;
width:100%;
}
tr #leftcol
{
width:30%;
}
table tr.note
{
background-color:white;
border-bottom-style: hidden;
}
span.note
{
font-style: italic;
font-size: 0.8em;
}
span.attention
{
font-style: italic;
color:red;
}
.filename
{
background-color: #f8ffff;
}
#filename
{
font-style: italic;
/*font-weight: bold; */
color:black; /*009d8f*/
}
/* Highlight when hovering over table rows: */
tr:hover {background-color: #e6ffff}
/* Stiped table: */
/*tr:nth-child(even) {background-color: #f2f2f2} */
th, td
{
padding: .5em 1em;
......@@ -71,12 +115,6 @@ a:active { color: red; }
Layout styles
------------------------*/
#logo {
position: absolute;
top: 0;
right: 0;
height: 5.25em;
}
.container
{
......@@ -84,14 +122,23 @@ Layout styles
margin: 0 auto;
}
.header
.lightgrey
{
color: #fff;
background: #005191;
padding: 1em 1.25em;
color: lightgrey;
margin: 8em 0 0 0;
}
.section
{
}
.lightgrey td
{
color: lightgrey;
}
.header-heading { margin: 0; }
.nav-bar
{
......@@ -229,17 +276,55 @@ Single styles
padding-left: 5px;
}
/* NARROW */
img#logo
{
height: 40px;
align:top;
}
.lpcontent { padding: 0em 0em; }
.section { padding: 1.5em 0.5em; }
.header { padding: 0em 0.5em; }
p#intro
{
font-size: 1.2em;
}
/* -----------------------
Wide styles
------------------------*/
@media (min-width: 42em)
/*@media (min-width: 42em)*/
@media (min-width: 60em)
{
.header { padding: 1.5em 3em; }
.header { padding: 1.5em 2.5em; }
.nav-bar { padding: 1em 3em; }
.content { padding: 2em 3em; }
.footer { padding: 2em 3em; }
p { padding: 1em 3em; }
.lpcontent { padding: 1em 2em; }
.section { padding: 2em 2em; }
img#logo
{
position: absolute;
right:2em; /*match padding of lpcontent */
top:1em; /*match padding of lpcontent */
height: 70px;
}
div.dkrz img#logo
{
padding: 5px 10px 5px 5px;
}
{
}
div.cmip6 img#logo
{
top:0px;
height: 100px;
}
}
.nav li
......@@ -254,4 +339,36 @@ Wide styles
padding: 0;
border-bottom: 0;
}
}
\ No newline at end of file
}
a#source{
height: 30px;
line-height:10px;
}
img#source{
height: 30px;
line-height:10px;
vertical-align: middle;
}
.header
{
color: #fff;
background: #005191;
padding: 1em 1.25em;
}
.dkrz.header
{
color: #fff;
background: #005191;
}
.cmip6.header
{
color: #009d8f; /*dark green*/
background: #caf7f7; /*green*/
}
<html>
<link rel="stylesheet" href="/static/styles.css" type="text/css">
<head>
<title>CMIP6 Landing Page</title>
<link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" />
</head>
<body class="lpcontent">
<div class="header cmip6">
<img id="logo" src="/static/cmip6logo2.png" alt="CMIP6 logo">
<h1>CMIP6 Data Information View</h1>
</div>
<!--<div class="lpcontent filename">
<h1>File <span id="filename">{{file_name}}</span></h1>
</div>-->
<div class="section">
<h1><em>{{file_name}}</em> (file)</h1>
<!--p id="intro">This is the information page of the persistent identifier of the CMIP6 file {{file_name}}.</p-->
</div>
<div class="section">
<h2>General information</h2>
<table>
{% if file_name %}
<tr>
<td id="leftcol">File name</td>
<td>{{file_name}}</td>
</tr>
{% endif %}
<tr>
<td id="leftcol">Persistent identifier</td>
<td><a href="http://hdl.handle.net/{{handle}}">hdl:{{handle}}</a></td>
</tr>
{% if file_size %}
<tr>
<td id="leftcol">File size</td>
<td>{{file_size}}</td>
</tr>
{% endif %}
{% if checksum and not checksum_method%}
<tr>
<td id="leftcol">Checksum</td>
<td>{{checksum}}</td>
</tr>
{% else %}
{% if checksum and checksum_method %}
<tr>
<td id="leftcol">Checksum ({{checksum_method}})</td>
<td>{{checksum}}</td>
</tr>
{% endif %}{% endif %}
</table>
</div>
<div class="section">
<h2>Data access</h2>
{% if urls_original or urls_replica %}
<table>
{% if urls_original %}
{% for entry in urls_original %}
<tr>
<td id="leftcol">Hosted by {{entry.host}}:</td>
<td><a href="{{entry.url}}">{{entry.url}}</a></td>
</tr>
{% endfor %}
{% endif %}
{% if urls_replicas %}
{% for entry in urls_replicas %}
<tr>
<td id="leftcol">Mirrored at {{entry.host}}:</td>
<td><a href="{{entry.url}}">{{entry.url}}</a> (Replica)</td>
</tr>
{% endfor %}
{% endif %}
</table>
{% endif %}
</div>
<div class="section">
<h2>The file is part of the following aggregation(s)</em></h2>
{% if parents_info %}
<table>
{% for item in parents_info %}
<tr>
<td id="leftcol">{{item.level}}</td>
<td>
{{ item.drs }} (version {{ item.version }})
<br/><a href="http://hdl.handle.net/{{ item.handle }}/">hdl:{{ item.handle }}</a>
{% if item.replaced %}
<br/><span class="attention">Attention, this {{item.level}} was replaced by a newer version!*</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% if any_parent_replaced %}
<tr class="note">
<td colspan="2"><span class="note">
<strong>* Note:</strong> If a dataset was replaced by a newer version, it is possible that there was an issue with this file, but not necessarily. It is also possible that the dataset was replaced due to problems in other files or due to lacking files. Please refer to the dataset's errata description to get more information. You can find information on the errata on the dataset's landing page or at the ESGF Errata Service.</span>
</td>
</tr>
{% endif %}
</table>
{% else %}{% if parents_list %}
<table>
{% for handle in parents_list %}
<tr><td><a href="http://hdl.handle.net/{{ handle }}/">{{ handle }}</a></td></tr>
{% endfor %}
</table>
{% else %}
<p>No information on which aggregations this handle belongs to.</p>
{% endif %}{% endif %}
</div>
<div class="section">
<p><span class="note">This PID landing page service is provided by <a id="source" href="http://dkrz.de"><img id="source" src="/static/dkrzlogo_white.png" alt="DKRZ logo"></a> (German Climate Computing Centre).</span></p>
</div>
<div class="section lightgrey">
<h2>Content of this handle record</h2>
<table>
{% for key,value in values.items %}
<tr>
<td id="leftcol">{{key}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="section lightgrey">
<h2>Content of this handle record (JSON)</h2>
<p>{{content}}</p>
</div>
</body>
</html>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment