claim explorer implementation

This commit is contained in:
Akinwale Ariwodola 2017-06-15 23:18:47 +01:00
parent 6018338b87
commit 78f51e89b4
7 changed files with 517 additions and 15 deletions

View file

@ -47,6 +47,7 @@ Router::scope('/', function (RouteBuilder $routes) {
$routes->connect('/', ['controller' => 'Main', 'action' => 'index']);
$routes->connect('/address/*', ['controller' => 'Main', 'action' => 'address']);
$routes->connect('/blocks/*', ['controller' => 'Main', 'action' => 'blocks']);
$routes->connect('/claims/*', ['controller' => 'Main', 'action' => 'claims']);
$routes->connect('/find', ['controller' => 'Main', 'action' => 'find']);
$routes->connect('/realtime', ['controller' => 'Main', 'action' => 'realtime']);
$routes->connect('/tx/*', ['controller' => 'Main', 'action' => 'tx']);
@ -69,4 +70,3 @@ Router::scope('/', function (RouteBuilder $routes) {
* how to customize the loading of plugin routes.
*/
Plugin::routes();

View file

@ -56,13 +56,6 @@ class MainController extends AppController {
if ($diffMinutes >= 15) { // 15 minutes
$shouldRefreshPrice = true;
}
/*
$diffHours = $diff->h;
$diffHours = $diffHours + ($diff->days * 24);
if ($diffHours >= 3) {
$shouldRefreshPrice = true;
}*/
}
}
@ -114,6 +107,62 @@ class MainController extends AppController {
$this->set('hashRate', $hashRate);
}
public function claims($id = null) {
$this->loadModel('Claims');
$this->loadModel('Transactions');
if (!$id) {
$claims = $this->Claims->find()->contain(['Stream', 'Publisher' => ['fields' => ['Name']]])->order(['Claims.Created' => 'DESC'])->limit(96)->toArray();
for ($i = 0; $i < count($claims); $i++) {
if (isset($claims[$i]->Stream)) {
$json = json_decode($claims[$i]->Stream->Stream);
if (isset($json->metadata->license)) {
$claims[$i]->License = $json->metadata->license;
}
if (isset($json->metadata->licenseUrl)) {
$claims[$i]->LicenseUrl = $json->metadata->licenseUrl;
}
}
}
$this->set('claims', $claims);
} else {
$claim = $this->Claims->find()->contain(['Stream', 'Publisher' => ['fields' => ['ClaimId', 'Name']]])->where(['Claims.ClaimId' => $id])->first();
if (!$claim) {
return $this->redirect('/');
}
$json = json_decode($claim->Stream->Stream);
if (isset($json->metadata->license)) {
$claim->License = $json->metadata->license;
}
if (isset($json->metadata->licenseUrl)) {
$claim->LicenseUrl = $json->metadata->licenseUrl;
}
$moreClaims = [];
if (isset($claim->Publisher)) {
// find more claims for the publisher
$moreClaims = $this->Claims->find()->contain(['Stream', 'Publisher' => ['fields' => ['Name']]])->
where(['Claims.ClaimType' => 2, 'Claims.Id <>' => $claim->Id, 'Claims.PublisherId' => $claim->Publisher->ClaimId])->
limit(9)->order(['RAND()' => 'DESC'])->toArray();
for ($i = 0; $i < count($moreClaims); $i++) {
if (isset($moreClaims[$i]->Stream)) {
$json = json_decode($moreClaims[$i]->Stream->Stream);
if (isset($json->metadata->license)) {
$moreClaims[$i]->License = $json->metadata->license;
}
if (isset($json->metadata->licenseUrl)) {
$moreClaims[$i]->LicenseUrl = $json->metadata->licenseUrl;
}
}
}
}
$this->set('claim', $claim);
$this->set('moreClaims', $moreClaims);
}
}
public function realtime() {
$this->loadModel('Blocks');
$this->loadModel('Transactions');
@ -187,6 +236,7 @@ class MainController extends AppController {
}
$this->loadModel('Blocks');
$this->loadModel('Claims');
$this->loadModel('Addresses');
$this->loadModel('Transactions');
@ -196,13 +246,19 @@ class MainController extends AppController {
if ($block) {
return $this->redirect('/blocks/' . $height);
}
} else if (strlen(trim($criteria)) <= 40) {
} else if (strlen(trim($criteria)) === 34) {
// Address
$address = $this->Addresses->find()->select(['Id', 'Address'])->where(['Address' => $criteria])->first();
if ($address) {
return $this->redirect('/address/' . $address->Address);
}
} else {
} else if (strlen(trim($criteria)) === 40) {
// Claim ID
$claim = $this->Claims->find()->select(['ClaimId'])->where(['ClaimId' => $criteria])->first();
if ($claim) {
return $this->redirect('/claim/' . $claim->ClaimId);
}
} else if (strlen(trim($criteria)) === 64) { // block or tx hash
// Try block hash first
$block = $this->Blocks->find()->select(['Height'])->where(['Hash' => $criteria])->first();
if ($block) {
@ -213,6 +269,12 @@ class MainController extends AppController {
return $this->redirect('/tx/' . $tx->Hash);
}
}
} else {
// finally, try exact claim name match
$claim = $this->Claims->find()->select(['ClaimId'])->where(['Name' => $criteria])->first();
if ($claim) {
return $this->redirect('/claims/' . $claim->ClaimId);
}
}
// Not found, redirect to index

View file

@ -20,6 +20,14 @@ class ClaimsTable extends Table {
'bindingKey' => 'ClaimId',
'propertyName' => 'Publisher'
]
],
'hasOne' => [
'Stream' => [
'className' => 'App\Model\Table\ClaimStreamsTable',
'foreignKey' => 'Id',
'bindingKey' => 'Id',
'propertyName' => 'Stream'
]
]
]);
}

View file

@ -5,7 +5,7 @@
<div class="search">
<form method="get" action="/find">
<div class="input-group">
<input type="text" name="q" placeholder="Enter a block height or hash, transaction hash or address" />
<input type="text" name="q" placeholder="Block height or hash, address, claim id or transaction hash" />
<button class="btn btn-inline-search">Search</button>
</div>
</form>

View file

@ -0,0 +1,344 @@
<?php $this->start('script'); ?>
<script type="text/javascript">
var resizeCards = function() {
var claimInfo = $('.claim-info');
var claimMtdt = $('.claim-metadata');
if (claimMtdt.outerHeight() < claimInfo.outerHeight()) {
claimMtdt.outerHeight(claimInfo.outerHeight());
} else if (claimInfo.outerHeight() < claimMtdt.outerHeight()) {
claimInfo.outerHeight(claimMtdt.outerHeight());
}
};
window.onload = function() {
resizeCards();
};
$(document).ready(function() {
resizeCards();
$('.claim-grid-item img,.claim-info img').on('error', function() {
var img = $(this);
var parent = img.parent();
var text = parent.attr('data-autothumb');
img.remove();
parent.append(
$('<div></div>').attr({'class': 'autothumb' }).text(text)
);
});
$(document).on('click', '.claim-grid-item', function() {
var id = $(this).attr('data-id');
location.href = '/claims/' + id;
});
});
</script>
<?php $this->end(); ?>
<?php echo $this->element('header') ?>
<?php if (isset($claim)):
$a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
$autoThumbText = '';
$link = $claim->Name;
if (isset($claim->Publisher->Name)) {
$link = $claim->Publisher->Name . '/' . $link;
}
$link = 'lbry://' . $link;
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 10 ))); } else {
$str = str_replace(' ', '', (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name);
$autoThumbText = strtoupper(substr($str, 0, min( strlen($str), 10 )));
}
$desc = $claim->Description;
if (strlen(trim($desc)) == 0) {
$desc = '<em>No description available.</em>';
} else {
$desc = preg_replace('#((https?|ftp)://(\S*?\.\S*?))([\s)\[\]{},;"\':<]|\.\s|$)#i','<a href="$1" target="_blank">$1</a>$4', $desc);
$desc = preg_replace('/(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/is', '<a href="mailto:$0">$0</a>', $desc);
}
?>
<?php $this->assign('title', 'Claim &bull; ' . $claim->Name) ?>
<div class="claims-head">
<h3><a href="/claims">LBRY Claims</a> &bull; <?php echo $claim->Name ?></h3>
<h4><?php echo $claim->ClaimId ?></h4>
</div>
<div class="claims-body">
<div class="claim-info">
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
<?php if (!$claim->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
<img src="<?php echo $claim->ThumbnailUrl ?>" alt="" />
<?php else: ?>
<div class="autothumb"><?php echo $autoThumbText ?></div>
<?php endif; ?>
</div>
<div class="content">
<?php if ($claim->ClaimType == 2): ?>
<div class="label">Published by</div>
<div class="value">
<?php if (isset($claim->Publisher)): ?>
<a href="lbry://<?php echo $claim->Publisher->Name ?>"><?php echo $claim->Publisher->Name ?></a>
<?php else: ?>
<em>Anonymous</em>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="label">Created</div>
<div class="value"><?php echo $claim->Created->format('j M Y H:i:s') ?> UTC</div>
<div class="label">Transaction</div>
<div class="value"><a href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>"><?php echo $claim->TransactionHash ?></a></div>
<?php if ($claim->ClaimType == 2): ?>
<div class="label">NSFW</div>
<div class="value"><?php echo $claim->IsNSFW ? 'Yes' : 'No' ?></div>
<?php endif; ?>
</div>
</div>
<div class="claim-metadata">
<?php if ($claim->ClaimType == 1): ?>
<div class="title">Identity Claim</div>
<div class="desc">This is an identity claim.</div>
<?php else: ?>
<div class="title"><?php echo $claim->Title ?></div>
<div class="desc"><?php echo str_replace("\n", '<br />', $desc) ?></div>
<div class="details">
<div class="label half-width">Author</div>
<div class="label half-width">Content Type</div>
<div class="value half-width"><?php echo strlen(trim($claim->Author)) > 0 ? $claim->Author : '<em>Unspecified</em>' ?></div>
<div class="value half-width"><?php echo strlen(trim($claim->ContentType)) > 0 ? $claim->ContentType : '<em>Unspecified</em>' ?></div>
<div class="label half-width">License</div>
<div class="label half-width">Language</div>
<div class="value half-width"<?php if(strlen(trim($claim->License)) > 0): ?> title="<?php echo $claim->License ?>"<?php endif; ?>>
<?php if (strlen(trim($claim->LicenseUrl)) > 0): ?><a href="<?php echo $claim->LicenseUrl ?>" rel="nofollow"><?php endif; ?>
<?php echo strlen(trim($claim->License)) > 0 ? $claim->License : '<em>Unspecified</em>' ?>
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
</div>
<div class="value half-width"><?php echo strlen(trim($claim->Language)) > 0 ? ($claim->Language == 'en' ? 'English' : '') : '<em>Unspecified</em>' ?></div>
</div>
<?php endif; ?>
<a href="<?php echo $link ?>" class="open-lbry-link">Open in LBRY</a>
</div>
<div class="clear"></div>
<?php if (count($moreClaims) > 0): ?>
<div class="more-claims">
<h4>More from the publisher</h4>
<div class="claims-grid">
<?php $idx = 1; $row = 1; $rowCount = ceil(count($moreClaims) / 3); foreach ($moreClaims as $claim):
$last_row = ($row == $rowCount);
if ($idx % 3 == 0) {
$row++;
}
$autoThumbText = '';
$link = $claim->Name;
if (isset($claim->Publisher->Name)) {
$link = $claim->Publisher->Name . '/' . $link;
}
$link = 'lbry://' . $link;
// content type
$ctTag = null;
if (substr($claim->ContentType, 0, 5) === 'audio') {
$ctTag = 'audio';
} else if (substr($claim->ContentType, 0, 5) === 'video') {
$ctTag = 'video';
} else if (substr($claim->ContentType, 0, 5) === 'image') {
$ctTag = 'image';
}
if (!$ctTag && $claim->ClaimType == 1) {
$ctTag = 'identity';
}
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 10 ))); } else {
$str = str_replace(' ', '', (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name);
$autoThumbText = strtoupper(substr($str, 0, min( strlen($str), 10 )));
}
?>
<div data-id="<?php echo $claim->ClaimId ?>" class="claim-grid-item<?php if ($idx % 3 == 0): ?> last-item<?php endif; ?><?php if ($last_row): ?> last-row<?php endif; ?>">
<div class="tags">
<?php if ($ctTag): ?>
<div class="content-type"><?php echo strtoupper($ctTag) ?></div>
<?php endif; ?>
<?php if ($claim->IsNSFW): ?>
<div class="nsfw">NSFW</div>
<?php endif; ?>
</div>
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
<?php if (!$claim->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
<img src="<?php echo $claim->ThumbnailUrl ?>" alt="" />
<?php else: ?>
<div class="autothumb"><?php echo $autoThumbText ?></div>
<?php endif; ?>
</div>
<div class="metadata">
<div class="title"><?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '<em>No Title</em>') ?></div>
<div class="link"><a href="<?php echo $link ?>" rel="nofollow"><?php echo $link ?></a></div>
<div class="desc"><?php echo strlen(trim($claim->Description)) > 0 ? $claim->Description : '<em>No description available</em>' ?></div>
<div class="label half-width">Transaction</div>
<div class="label half-width">Created</div>
<div class="value half-width"><a href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>" title="<?php echo $claim->TransactionHash ?>"><?php echo $claim->TransactionHash ?></a></div>
<div class="value half-width" title="<?php echo $claim->Created->format('j M Y H:i:s') ?> UTC">
<?php echo \Carbon\Carbon::createFromTimestamp($claim->Created->format('U'))->diffForHumans(); ?>
</div>
<div class="clear spacer"></div>
<?php if ($claim->ClaimType == 2): ?>
<div class="label half-width">Content type</div>
<div class="label half-width">Language</div>
<div class="value half-width"><?php echo $claim->ContentType ?></div>
<div class="value half-width"><?php echo $claim->Language == 'en' ? 'English' : $claim->Language ?></div>
<div class="clear spacer"></div>
<div class="label half-width">Author</div>
<div class="label half-width">License</div>
<div class="value half-width"><?php echo strlen(trim($claim->Author)) > 0 ? $claim->Author : '<em>Unspecified</em>' ?></div>
<div class="value half-width">
<?php if (strlen(trim($claim->LicenseUrl)) > 0): ?><a href="<?php echo $claim->LicenseUrl ?>" rel="nofollow"><?php endif; ?>
<?php echo strlen(trim($claim->License)) > 0 ? $claim->License : '<em>Unspecified</em>' ?>
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php $idx++; endforeach; ?>
<div class="clear"></div>
</div>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<?php $this->assign('title', 'Claims Explorer') ?>
<div class="claims-head">
<h2>Claims Explorer</h2>
</div>
<div class="claims-grid">
<?php $idx = 1; $a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow']; foreach ($claims as $claim):
$last_row = (count($claims) - $idx < 3);
$autoThumbText = '';
$link = $claim->Name;
if (isset($claim->Publisher->Name)) {
$link = $claim->Publisher->Name . '/' . $link;
}
$link = 'lbry://' . $link;
// content type
$ctTag = null;
if (substr($claim->ContentType, 0, 5) === 'audio') {
$ctTag = 'audio';
} else if (substr($claim->ContentType, 0, 5) === 'video') {
$ctTag = 'video';
} else if (substr($claim->ContentType, 0, 5) === 'image') {
$ctTag = 'image';
}
if (!$ctTag && $claim->ClaimType == 1) {
$ctTag = 'identity';
}
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 10 ))); } else {
$str = str_replace(' ', '', (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name);
$autoThumbText = strtoupper(substr($str, 0, min( strlen($str), 10 )));
}
?>
<div data-id="<?php echo $claim->ClaimId ?>" class="claim-grid-item<?php if ($idx % 3 == 0): ?> last-item<?php endif; ?><?php if ($last_row): ?> last-row<?php endif; ?>">
<div class="tags">
<?php if ($ctTag): ?>
<div class="content-type"><?php echo strtoupper($ctTag) ?></div>
<?php endif; ?>
<?php if ($claim->IsNSFW): ?>
<div class="nsfw">NSFW</div>
<?php endif; ?>
</div>
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
<?php if (!$claim->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
<img src="<?php echo $claim->ThumbnailUrl ?>" alt="" />
<?php else: ?>
<div class="autothumb"><?php echo $autoThumbText ?></div>
<?php endif; ?>
</div>
<div class="metadata">
<div class="title"><?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '<em>No Title</em>') ?></div>
<div class="link"><a href="<?php echo $link ?>" rel="nofollow"><?php echo $link ?></a></div>
<div class="desc"><?php echo strlen(trim($claim->Description)) > 0 ? $claim->Description : '<em>No description available</em>' ?></div>
<div class="label half-width">Transaction</div>
<div class="label half-width">Created</div>
<div class="value half-width"><a href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>" title="<?php echo $claim->TransactionHash ?>"><?php echo $claim->TransactionHash ?></a></div>
<div class="value half-width" title="<?php echo $claim->Created->format('j M Y H:i:s') ?> UTC">
<?php echo \Carbon\Carbon::createFromTimestamp($claim->Created->format('U'))->diffForHumans(); ?>
</div>
<div class="clear spacer"></div>
<?php if ($claim->ClaimType == 2): ?>
<div class="label half-width">Content type</div>
<div class="label half-width">Language</div>
<div class="value half-width"><?php echo $claim->ContentType ?></div>
<div class="value half-width"><?php echo $claim->Language == 'en' ? 'English' : $claim->Language ?></div>
<div class="clear spacer"></div>
<div class="label half-width">Author</div>
<div class="label half-width">License</div>
<div class="value half-width"><?php echo strlen(trim($claim->Author)) > 0 ? $claim->Author : '<em>Unspecified</em>' ?></div>
<div class="value half-width">
<?php if (strlen(trim($claim->LicenseUrl)) > 0): ?><a href="<?php echo $claim->LicenseUrl ?>" rel="nofollow"><?php endif; ?>
<?php echo strlen(trim($claim->License)) > 0 ? $claim->License : '<em>Unspecified</em>' ?>
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php $idx++; endforeach; ?>
<div class="clear"></div>
</div>
<?php endif ?>

View file

@ -95,7 +95,7 @@
<div class="main">
<div class="title">LBRY Block Explorer</div>
<form method="get" action="/find">
<input class="search-input" name="q" type="text" placeholder="Enter a block height or hash, transaction hash or address" />
<input class="search-input" name="q" type="text" placeholder="Enter a block height or hash, claim id or name, transaction hash or address" />
<div class="ctls"><button class="btn btn-search">Search</button> <a href="/realtime">Realtime</a></div>
</form>
</div>
@ -155,8 +155,9 @@
<div class="recent-claims">
<h3>Recent Claims</h3>
<?php $idx = 0; foreach ($recentClaims as $claim):
$idx++; $a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
<a class="claim-explorer-link" href="/claims">Claim Explorer</a>
<?php $idx = 0; $a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow']; foreach ($recentClaims as $claim):
$idx++;
$autoThumbText = '';
$link = $claim->Name;
if (isset($claim->Publisher->Name)) {

View file

@ -17,7 +17,7 @@ border-radius: 0 6px 8px 0 }
.header .search .input-group .btn-inline-search:hover { background: #1976d2 }
.home-container-cell > .main > .title { font-family: 'adelle-sans', sans-serif; font-weight: bold; font-size: 280%; margin: 24px auto 24px auto; width: 600px; text-align: center; color: #333; cursor: default }
.home-container-cell .search-input { display: block; margin: 0 auto; padding: 8px; text-align: center; border: 3px solid #ddd; border-radius: 16px; width: 600px; font-size: 115%; font-weight: 300 }
.home-container-cell .search-input { display: block; margin: 0 auto; padding: 8px; text-align: center; border: 3px solid #ddd; border-radius: 16px; width: 720px; font-size: 115%; font-weight: 300 }
.home-container-cell .ctls { width: 600px; text-align: center; margin: 24px auto; position: relative }
.home-container-cell .ctls .btn-search { font-size: 115%; display: inline-block; padding: 12px 48px; background: #1e88e5; color: #fff; border-radius: 8px; border: none; font-weight: 300; cursor: pointer }
.home-container-cell .ctls .btn-search:hover { background: #1976d2 }
@ -27,6 +27,31 @@ border-radius: 0 6px 8px 0 }
.home-container-cell .recent-blocks { width: 1000px; margin: 48px auto 0 auto; box-shadow: 0 2px 6px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px 24px 36px 24px; cursor: default }
.home-container-cell .recent-blocks h3 { font-weight: normal; margin: 0 0 12px 0; font-weight: 300 }
.home-container-cell .recent-claims { width: 1000px; margin: 48px auto 0 auto; box-shadow: 0 2px 6px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px 24px 36px 24px; cursor: default; position: relative }
.home-container-cell .recent-claims .claim-explorer-link { position: absolute; right: 32px; top: 24px; font-size: 80% }
.home-container-cell .recent-claims h3 { font-weight: normal; margin: 0 0 12px 0; font-weight: 300 }
.home-container-cell .recent-claims .claim-box { width: 184px; height: 330px; margin-right: 7px; float: left; box-shadow: 0 2px 4px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); cursor: default; overflow: hidden; position: relative }
.home-container-cell .recent-claims .claim-box.last { margin-right: 0 }
.home-container-cell .recent-claims .claim-box .tags { font-size: 65%; position: absolute; right: 0; top: 0; z-index: 505 }
.home-container-cell .recent-claims .claim-box .thumbnail { width: 100%; height: 120px; background: #f0f0f0; display: block; position: relative; overflow: hidden;}
.home-container-cell .recent-claims .claim-box .thumbnail img { width: 100%; position: absolute; left: 0; top: 0; border-bottom: 1px solid #eee }
.home-container-cell .recent-claims .claim-box .thumbnail.purple { background: #ab47bc }
.home-container-cell .recent-claims .claim-box .thumbnail.orange { background: #e91e63 }
.home-container-cell .recent-claims .claim-box .thumbnail.blue { background: #42a5f5 }
.home-container-cell .recent-claims .claim-box .thumbnail.teal { background: #4db6ac }
.home-container-cell .recent-claims .claim-box .thumbnail.green { background: #66bb6a }
.home-container-cell .recent-claims .claim-box .thumbnail.yellow { background: #fdd835 }
.home-container-cell .recent-claims .claim-box .thumbnail .autothumb { display: block; margin: 33px auto 0 auto; text-align: center; font-size: 240%; color: #fff; line-height: 54px }
.home-container-cell .recent-claims .claim-box .tags > div { display: inline-block; padding: 4px 12px; margin-left: 2px }
.home-container-cell .recent-claims .claim-box .tags .nsfw { background: #e53935; text-align: center; color: #fff; position: relative; left: 1px }
.home-container-cell .recent-claims .claim-box .tags .content-type { background: #880e4f; text-align: center; color: #fff; }
.home-container-cell .recent-claims .claim-box .metadata { padding: 12px; font-size: 90% }
.home-container-cell .recent-claims .claim-box .title { font-size: 120%; height: 25px; line-height: 25px; overflow: hidden; text-overflow: ellipsis }
.home-container-cell .recent-claims .claim-box .desc { font-size: 80%; font-weight: 300; height: 100px; overflow: hidden; text-overflow: ellipsis; margin: 3px 0; line-height: 20px }
.home-container-cell .recent-claims .claim-box .link { font-size: 80%; font-weight: 300; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; line-height: 20px; height: 20px }
.home-container-cell .recent-claims .claim-box .tx-link { font-size: 80%; font-weight: 300; color: #fff; background: #1e88e5; position: absolute; bottom: 0; width: 100%; display: block; line-height: 20px; height: 32px; padding: 6px 0; text-align: center; cursor: pointer }
.home-container-cell .recent-claims .claim-box .tx-link:hover { text-decoration: none; background: #1976d2 }
.home-container-cell .recent-claims { width: 1000px; margin: 48px auto 0 auto; box-shadow: 0 2px 6px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px 24px 36px 24px; cursor: default }
.home-container-cell .recent-claims h3 { font-weight: normal; margin: 0 0 12px 0; font-weight: 300 }
.home-container-cell .recent-claims .claim-box { width: 184px; height: 330px; margin-right: 7px; float: left; box-shadow: 0 2px 4px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); cursor: default; overflow: hidden; position: relative }
@ -51,6 +76,68 @@ border-radius: 0 6px 8px 0 }
.home-container-cell .recent-claims .claim-box .tx-link { font-size: 80%; font-weight: 300; color: #fff; background: #1e88e5; position: absolute; bottom: 0; width: 100%; display: block; line-height: 20px; height: 32px; padding: 6px 0; text-align: center; cursor: pointer }
.home-container-cell .recent-claims .claim-box .tx-link:hover { text-decoration: none; background: #1976d2 }
.claims-head h2 { font-weight: 300; margin-bottom: 0; font-size: 220% }
.claims-head { width: 1200px; margin: 0 auto 24px auto; cursor: default }
.claims-head h3, h4 { font-weight: 300; margin: 0 }
.claims-head h3 { font-size: 200%; margin-bottom: 3px }
.claims-head h4 { font-size: 125% }
.claims-grid { width: 1200px; margin: 0 auto 0 auto; cursor: default }
.claims-grid .claim-grid-item { width: 360px; height: 560px; margin-right: 60px; margin-bottom: 60px; float: left; box-shadow: 0 2px 4px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); cursor: default; overflow: hidden; position: relative; cursor: pointer }
.claims-grid .claim-grid-item:hover { background: #fbfbfb }
.claims-grid .claim-grid-item.last-item { margin-right: 0 }
.claims-grid .claim-grid-item.last-row { margin-bottom: 0 }
.claims-grid .claim-grid-item .tags { font-size: 65%; position: absolute; right: 0; top: 0; z-index: 505 }
.claims-grid .claim-grid-item .thumbnail { width: 100%; height: 200px; background: #f0f0f0; display: block; position: relative; overflow: hidden;}
.claims-grid .claim-grid-item .thumbnail img { width: 100%; position: absolute; left: 0; top: 0; border-bottom: 1px solid #eee }
.claims-grid .claim-grid-item .thumbnail.purple { background: #ab47bc }
.claims-grid .claim-grid-item .thumbnail.orange { background: #e91e63 }
.claims-grid .claim-grid-item .thumbnail.blue { background: #42a5f5 }
.claims-grid .claim-grid-item .thumbnail.teal { background: #4db6ac }
.claims-grid .claim-grid-item .thumbnail.green { background: #66bb6a }
.claims-grid .claim-grid-item .thumbnail.yellow { background: #fdd835 }
.claims-grid .claim-grid-item .thumbnail .autothumb { display: block; margin: 73px auto 0 auto; text-align: center; font-size: 240%; color: #fff; line-height: 54px }
.claims-grid .claim-grid-item .tags > div { display: inline-block; padding: 4px 12px; margin-left: 2px }
.claims-grid .claim-grid-item .tags .nsfw { background: #e53935; text-align: center; color: #fff; position: relative; left: 1px }
.claims-grid .claim-grid-item .tags .content-type { background: #880e4f; text-align: center; color: #fff; }
.claims-grid .claim-grid-item .metadata { padding: 24px; font-size: 90% }
.claims-grid .claim-grid-item .title { font-size: 120%; height: 25px; line-height: 25px; overflow: hidden; text-overflow: ellipsis }
.claims-grid .claim-grid-item .desc { font-size: 90%; font-weight: 300; height: 72px; overflow: hidden; text-overflow: ellipsis; margin: 8px 0 20px 0; line-height: 24px }
.claims-grid .claim-grid-item .link { font-size: 95%; font-weight: 300; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; line-height: 20px; height: 20px; margin-top: 6px }
.claims-grid .claim-grid-item .label { font-size: 80%; color: #1e88e5 }
.claims-grid .claim-grid-item .value { font-weight: 300; word-break: break-word; word-wrap: break-word; font-size: 95%; line-height: 24px; height: 24px }
.claims-grid .claim-grid-item .half-width { width: 155px; float: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 12px }
.claims-grid .claim-grid-item .spacer { height: 16px }
.claims-body { width: 1200px; margin: 0 auto 0 auto; cursor: default }
.claims-body .claim-info { width: 400px; float: left; box-shadow: 0 2px 4px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); cursor: default }
.claims-body .claim-info .thumbnail { width: 100%; height: 220px; background: #f0f0f0; display: block; position: relative; overflow: hidden }
.claims-body .claim-info .thumbnail img { width: 100% }
.claims-body .claim-info .content { padding: 24px }
.claims-body .claim-info .content .label { font-size: 90%; color: #1e88e5 }
.claims-body .claim-info .content .value { font-weight: 300; margin-bottom: 24px; word-break: break-word; word-wrap: break-word }
.claims-body .claim-info .content .value:last-child { margin-bottom: 0 }
.claims-body .claim-info .thumbnail.purple { background: #ab47bc }
.claims-body .claim-info .thumbnail.orange { background: #e91e63 }
.claims-body .claim-info .thumbnail.blue { background: #42a5f5 }
.claims-body .claim-info .thumbnail.teal { background: #4db6ac }
.claims-body .claim-info .thumbnail.green { background: #66bb6a }
.claims-body .claim-info .thumbnail.yellow { background: #fdd835 }
.claims-body .claim-info .thumbnail .autothumb { display: block; margin: 93px auto 0 auto; text-align: center; font-size: 240%; color: #fff; line-height: 54px }
.claims-body .claim-metadata { width: 750px; margin-left: 50px; float: left; box-shadow: 0 2px 4px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px 36px 88px 36px; cursor: default; position: relative }
.claims-body .claim-metadata .title { font-weight: 300; font-size: 170%; margin-bottom: 16px; color: #1e88e5; padding: 0 8px }
.claims-body .claim-metadata .desc { font-weight: 300; font-size: 130%; line-height: 36px; padding: 0 12px }
.claims-body .claim-metadata .details { margin-top: 36px; border-top: 1px solid #ddd; padding: 36px 16px 0 16px }
.claims-body .claim-metadata .details .label { font-size: 90%; color: #1e88e5 }
.claims-body .claim-metadata .details .value { font-size: 110%; font-weight: 300; margin-bottom: 24px }
.claims-body .claim-metadata .details .half-width { width: 50%; padding-right: 36px; float: left; height: 25px; line-height: 25px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis }
.claims-body .claim-metadata .open-lbry-link { position: absolute; right: 36px; bottom: 36px; padding: 10px 24px; color: #fff; font-weight: 300; font-size: 90%; background: #1e88e5 }
.claims-body .claim-metadata .open-lbry-link:hover { text-decoration: none; background: #1976d2 }
.claims-body .more-claims { margin-top: 64px }
.claims-body .more-claims h4 { color: #1e88e5; font-weight: 300; font-size: 160%; margin-bottom: 16px }
.table { width: 100%; cursor: default; border-collapse: collapse; font-size: 90% }
.table thead tr th { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; padding: 12px 4px }
.table tbody tr td { padding: 8px; border-bottom: 1px solid #eee; font-weight: 300; white-space: nowrap }