bounty program 1.0

This commit is contained in:
Jeremy Kauffman 2016-08-03 10:03:05 -04:00
parent 369d72a9f5
commit 7bab13881d
14 changed files with 187 additions and 86 deletions

View file

@ -6,16 +6,18 @@ class BountyActions extends Actions
public static function executeList()
{
$allBounties = Post::find(ROOT_DIR . '/posts/bounty');
$allCategories = ['' => ''] + Post::collectMetadata($allBounties, 'category');
$allStatuses = ['' => ''] + Post::collectMetadata($allBounties, 'status');
$selectedStatus = static::param('status');
$selectedCategory = static::param('category');
$filters = array_filter(['category' => $selectedCategory, 'status' => $selectedStatus]);
$allBounties = Post::find(ROOT_DIR . '/posts/bounty');
$allCategories = array_unique(array_map(function(Post $post) {
$metadata = $post->getMetadata();
return isset($metadata['category']) ? $metadata['category'] : null;
}, $allBounties));
$filters = array_filter([
'category' => $selectedCategory && isset($allCategories[$selectedCategory]) ? $selectedCategory : null,
'status' => $selectedStatus && isset($allStatuses[$selectedStatus]) ? $selectedStatus : null
]);
$bounties = $filters ? Post::filter($allBounties, $filters) : $allBounties;
@ -32,6 +34,7 @@ class BountyActions extends Actions
return ['bounty/list', [
'bounties' => $bounties,
'categories' => $allCategories,
'statuses' => $allStatuses,
'selectedCategory' => $selectedCategory,
'selectedStatus' => $selectedStatus
]];

View file

@ -23,9 +23,9 @@ class ContentActions extends Actions
public static function executeFaq()
{
$posts = Post::find(static::VIEW_FOLDER_FAQ);
$allPosts = Post::find(static::VIEW_FOLDER_FAQ);
$groupNames = [
$allCategories = array_merge(['' => ''] + Post::collectMetadata($allPosts, 'category'), [
'getstarted' => 'Getting Started',
'install' => 'Installing LBRY',
'running' => 'Running LBRY',
@ -35,17 +35,27 @@ class ContentActions extends Actions
'policy' => 'Policies',
'developer' => 'Developers',
'other' => 'Other Questions',
];
]);
$selectedCategory = static::param('category');
$filters = array_filter([
'category' => $selectedCategory && isset($allCategories[$selectedCategory]) ? $selectedCategory : null,
]);
$groups = array_fill_keys(array_keys($groupNames), []);
asort($allCategories);
$posts = $filters ? Post::filter($allPosts, $filters) : $allPosts ;
$groups = array_fill_keys(array_keys($allCategories), []);
foreach($posts as $post)
{
$groups[isset($groupNames[$post->getCategory()]) ? $post->getCategory() : 'other'][] = $post;
$groups[$post->getCategory()][] = $post;
}
return ['content/faq', [
'groupNames' => $groupNames,
'categories' => $allCategories,
'selectedCategory' => $selectedCategory,
'postGroups' => $groups
]];
}

View file

@ -8,6 +8,11 @@
#
#
bounty:
list:
noresult: No matching bounties found.
show:
completednotice: This bounty has already been completed and can no longer be claimed.
description:
allowed: Download/install the latest version of LBRY for %os%.
faq: Frequently asked questions about LBRY.

View file

@ -343,6 +343,16 @@ class Post
return strtolower(preg_replace('#^\d+\-#', '', basename(trim($filename), '.md')));
}
public static function collectMetadata(array $posts, $field)
{
$values = array_unique(array_map(function(Post $post) use($field) {
$metadata = $post->getMetadata();
return isset($metadata[$field]) ? $metadata[$field] : null;
}, $posts));
sort($values);
return array_combine($values, $values);
}
public static function getSlugMap($postType)
{
if (!isset(static::$slugMap[$postType]))

26
posts/faq/bounties.md Normal file
View file

@ -0,0 +1,26 @@
---
title: How does the Bounty Program work?
category: policy
---
You can earn LBRY Credits for completing tasks as part of the LBRY Bounty Program.
### What bounties are available?
All bounties can be seen on the [bounty home page](/bounty).
### How do I claim a bounty?
To claim a bounty, please email [bounty@lbry.io](mailto:bounty@lbry.io). Please include a link to the bounty. If it is programming related, please include a link to the pull request.
### How do I get compensated?
People who complete bounties are awarded LBRY credits. These credits will be transferred to a wallet address of your choice and are yours with no restrictions to do as you like.
### I have questions about a specific bounty or want assistance in completing a bounty.
The best place to get real-time help is our [Slack channel](https://slack.lbry.io). You can also email our bounty team [bounty@lbry.io](mailto:bounty@lbry.io).
### I want to complete a bounty that is not listed.
Send an email our bounty team at [bounty@lbry.io](mailto:bounty@lbry.io).

View file

@ -0,0 +1,4 @@
<div class="clearfix">
<span class="align-left"><span class="meta"><?php echo $metadata['category'] ?></span></span>
<span class="align-right"><span class="badge badge-primary bounty-award"><?php echo i18n::formatCredits($metadata['award']) ?></span></span>
</div>

View file

@ -2,7 +2,7 @@
<?php NavActions::setNavUri('/learn') ?>
<?php echo View::render('nav/_header', ['isDark' => false]) ?>
<main>
<div class="hero hero-quote hero-img spacer2" style="background-image: url(/img/fireworks.png)">
<div class="hero hero-quote hero-img hero-img-short spacer1" style="background-image: url(/img/fireworks.png)">
<div class="hero-content-wrapper">
<div class="hero-content text-center">
<h1 class="cover-title">LBRY Bounties</h1>
@ -12,23 +12,22 @@
</div>
<section class="content content-light">
<h3>Bounties</h3>
<p>Complete challenges and earn LBRY Credits. <a class="link-primary" href="/faq/bounties">Learn more</a>.</p>
<form method="get" action="/bounty" id="bounty-filter-form">
<div class="clearfix">
<div class="form-row align-left" style="margin-right: 10px">
<label>Category</label>
<select name="category">
<?php foreach($categories as $category): ?>
<option value="<?php echo $category ?>" <?php echo $selectedCategory == $category ? 'selected="selected"' : '' ?>>
<?php echo $category ?>
</option>
<?php endforeach ?>
</select>
<?php echo View::render('form/_select', [
'name' => 'category',
'choices' => $categories,
'selected' => $selectedCategory
]) ?>
</div>
<div class="form-row align-left">
<label>Completed</label>
<select name="status">
<?php foreach(['' => 'any', 'available' => 'available', 'completed' => 'completed'] as $statusVal => $statusLabel): ?>
<option value="<?php echo $statusVal ?>"><?php echo $statusLabel ?></option>
<?php foreach($statuses as $statusVal => $statusLabel): ?>
<option value="<?php echo $statusVal ?>" <?php echo $selectedStatus == $statusVal ? 'selected="selected"' : '' ?>><?php echo $statusLabel ?></option>
<?php endforeach ?>
</select>
</div>
@ -39,31 +38,31 @@
<?php js_end() ?>
</section>
<section class="content content-light">
<?php if (count($bounties)): ?>
<div class="tile-fluid clearfix spacer2">
<?php foreach($bounties as $post): ?>
<div class="span4">
<a class="bounty-tile" href="<?php echo $post->getRelativeUrl() ?>">
<div class="text-center spacer-half"><span class="icon-mega
<?php $metadata = $post->getMetadata() ?>
<div class="span4">
<a class="bounty-tile <?php echo isset($metadata['status']) ? 'bounty-status-' . $metadata['status'] : '' ?>" href="<?php echo $post->getRelativeUrl() ?>">
<div class="text-center spacer-half"><span class="icon-mega
<?php switch($metadata['category']) {
case 'ci': echo 'icon-wrench'; break;
case 'android': echo 'icon-android'; break;
case 'ios': echo 'icon-apple'; break;
case 'browser': echo 'icon-globe'; break;
case 'cif': echo 'icon-wrench'; break;
case 'cig': echo 'icon-wrench'; break;
case 'human': echo 'icon-users'; break;
default: echo 'icon-dollar'; break;
} ?>
"></span></div>
<h3 class="link-primary"><?php echo $post->getTitle() ?></h3>
<div class="clearfix">
<span class="align-left"><span class="meta"><?php echo $metadata['category'] ?></span></span>
<span class="align-right"><span class="badge badge-primary"><?php echo i18n::formatCredits($metadata['award']) ?></span></span>
</div>
<?php echo View::render('bounty/_meta', ['metadata' => $metadata]) ?>
</a>
</div>
<?php endforeach ?>
</div>
<?php else: ?>
<p><em>{{bounty.list.noresults}}</em></p>
<?php endif ?>
</section>
</main>
<?php echo View::render('nav/_footer') ?>

View file

@ -2,15 +2,31 @@
<?php NavActions::setNavUri('/learn') ?>
<?php echo View::render('nav/_header') ?>
<main>
<section class="post-content">
<div class="content">
<div class="post-content">
<div class="meta">
<br/>
<a href="/bounty">« Back to All Bounties</a>
<a href="/bounty" class="link-primary">« Back to All Bounties</a>
</div>
<section class="spacer2">
<h1><?php echo htmlentities($metadata['title']) ?></h1>
<div class="spacer1">
<?php echo View::render('bounty/_meta', ['metadata' => $metadata]) ?>
</div>
<?php if ($metadata['status'] == 'complete'): ?>
<div class="notice notice-info spacer1">{{bounty.show.completednotice}}</div>
<?php endif ?>
<?php echo $postHtml ?>
</section>
<section>
<h4>Claim This Bounty</h4>
<div class="spacer1">
<a href="mailto:bounty@lbry.io?subject=<?php echo $metadata['title'] ?>" class="btn btn-alt">Claim Bounty</a>
</div>
<h4>Bounty Questions?</h4>
<div class="spacer1">
<a href="/faq/bounties">Read the FAQ</a>
</div>
</section>
</div>
</main>
<?php echo View::render('nav/_footer', ['showLearnFooter' => true]) ?>

View file

@ -4,13 +4,29 @@
<main>
<section class="content content-readable spacer2">
<h1>{{page.faq.header}}</h1>
<?php foreach($postGroups as $group => $posts): ?>
<h2><?php echo $groupNames[$group] ?></h2>
<form method="get" action="/faq" id="faq-filter-form">
<div class="form-row">
<label>Category</label>
<?php echo View::render('form/_select', [
'name' => 'category',
'choices' => $categories,
'selected' => $selectedCategory
]) ?>
</div>
</form>
<?php js_start() ?>
$('#faq-filter-form').change(function() { $(this).submit(); });
<?php js_end() ?>
<?php foreach($postGroups as $category => $posts): ?>
<?php if (count($posts)): ?>
<h2><?php echo $categories[$category] ?></h2>
<?php foreach($posts as $post): ?>
<div class="spacer1">
<a href="<?php echo $post->getRelativeUrl() ?>" class="link-primary"><?php echo $post->getTitle() ?></a>
</div>
<?php endforeach ?>
<?php endif ?>
<?php endforeach ?>
</section>
</main>

View file

@ -0,0 +1,7 @@
<select name="<?php echo $name ?>">
<?php foreach($choices as $value => $label): ?>
<option value="<?php echo $value ?>" <?php echo $selected == $value ? 'selected="selected"' : '' ?>>
<?php echo $label ?>
</option>
<?php endforeach ?>
</select>

View file

@ -4,7 +4,8 @@
<?php if ($showLearnFooter): ?>
<?php echo View::render('nav/_learnFooter', ['isDark' => $isDark]) ?>
<?php endif ?>
<div class="content footer-standard">
<div class="footer-standard">
<div class="content">
<nav class="control-group">
<div class="control-item">
<a href="/"><?php echo __('nav.home') ?></a>
@ -18,4 +19,5 @@
</nav>
</div>
</div>
</div>
<?php endif ?>

View file

@ -97,7 +97,7 @@
margin-right: auto;
max-width: $max-post-content-width;
margin-bottom: $spacing-vertical * 2;
a[href]
a[href]:not([class])
{
@include anchor($color-primary);
}

View file

@ -1,15 +1,14 @@
.bounty-tile
{
.bounty-tile {
display: block;
margin: 0 10px $spacing-vertical;
padding: 10px;
background: #eee;
&:hover
{
&:hover {
cursor: pointer;
}
.icon-mega
{
}
}
.bounty-status-complete .bounty-award
{
text-decoration: line-through;
}

View file

@ -59,6 +59,10 @@
background: black url(/img/dark.png) no-repeat top center fixed;
min-height: 420px;
@include background-size(cover);
&.hero-img-short
{
min-height: 200px;
}
&:before
{
position: absolute;