mirror of
https://github.com/LBRYFoundation/lbry.com.git
synced 2025-08-23 17:47:26 +00:00
roadmap v1
This commit is contained in:
parent
a21e9b56b5
commit
c940a21ea6
17 changed files with 213 additions and 147 deletions
|
@ -86,9 +86,9 @@ class Controller
|
|||
case '/dl/lbry_setup.sh':
|
||||
return static::redirect('/get', 301);
|
||||
case '/get/lbry.dmg':
|
||||
return static::redirect(DownloadActions::getDownloadUrl(DownloadActions::OS_OSX) ?: '/get');
|
||||
return static::redirect(Github::getDownloadUrl(Os::OS_OSX) ?: '/get');
|
||||
case '/get/lbry.deb':
|
||||
return static::redirect(DownloadActions::getDownloadUrl(DownloadActions::OS_LINUX) ?: '/get');
|
||||
return static::redirect(Github::getDownloadUrl(Os::OS_LINUX) ?: '/get');
|
||||
case '/art':
|
||||
return static::redirect('/what', 301);
|
||||
case '/why':
|
||||
|
|
|
@ -15,10 +15,7 @@ class ContentActions extends Actions
|
|||
|
||||
public static function executeHome()
|
||||
{
|
||||
return ['page/home', [
|
||||
'totalUSD' => CreditApi::getTotalDollarSales(),
|
||||
'totalPeople' => CreditApi::getTotalPeople()
|
||||
]];
|
||||
return ['page/home'];
|
||||
}
|
||||
|
||||
public static function executeFaq()
|
||||
|
@ -114,7 +111,8 @@ class ContentActions extends Actions
|
|||
public static function executeRoadmap()
|
||||
{
|
||||
return ['content/roadmap', [
|
||||
'tasks' => Asana::listRoadmapTasks()
|
||||
'tasks' => Asana::listRoadmapTasks(),
|
||||
'changesets' => Github::listRoadmapChangesets()
|
||||
]];
|
||||
}
|
||||
|
||||
|
|
|
@ -2,23 +2,6 @@
|
|||
|
||||
class DownloadActions extends Actions
|
||||
{
|
||||
const OS_ANDROID = 'android',
|
||||
OS_IOS = 'ios',
|
||||
OS_LINUX = 'linux',
|
||||
OS_OSX = 'osx',
|
||||
OS_WINDOWS = 'windows';
|
||||
|
||||
public static function getOses()
|
||||
{
|
||||
return [
|
||||
static::OS_WINDOWS => ['/windows', 'Windows', 'icon-windows', '_windows'],
|
||||
static::OS_OSX => ['/osx', 'OS X', 'icon-apple', '_osx'],
|
||||
static::OS_LINUX => ['/linux', 'Linux', 'icon-linux', '_linux'],
|
||||
static::OS_ANDROID => ['/android', 'Android', 'icon-android', '_android'],
|
||||
static::OS_IOS => ['/ios', 'iOS', 'icon-mobile', '_ios']
|
||||
];
|
||||
}
|
||||
|
||||
public static function executeGet()
|
||||
{
|
||||
$email = static::param('e');
|
||||
|
@ -52,7 +35,7 @@ class DownloadActions extends Actions
|
|||
return ['download/get', ['os' => static::guessOs()]];
|
||||
}
|
||||
|
||||
$osChoices = static::getOses();
|
||||
$osChoices = Os::getAll();
|
||||
$os = static::guessOs();
|
||||
|
||||
if ($os && isset($osChoices[$os]))
|
||||
|
@ -64,7 +47,7 @@ class DownloadActions extends Actions
|
|||
'osIcon' => $osIcon,
|
||||
'prefineryUser' => $user ?: [],
|
||||
'downloadHtml' => View::exists('download/' . $partial) ?
|
||||
View::render('download/' . $partial, ['downloadUrl' => static::getDownloadUrl($os)]) :
|
||||
View::render('download/' . $partial, ['downloadUrl' => Github::getDownloadUrl($os)]) :
|
||||
false
|
||||
]];
|
||||
}
|
||||
|
@ -123,8 +106,8 @@ class DownloadActions extends Actions
|
|||
public static function prepareListPartial(array $vars)
|
||||
{
|
||||
return $vars + ['osChoices' => isset($vars['excludeOs']) ?
|
||||
array_diff_key(static::getOses(), [$vars['excludeOs'] => null]) :
|
||||
static::getOses()
|
||||
array_diff_key(Os::getAll(), [$vars['excludeOs'] => null]) :
|
||||
Os::getAll()
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -165,7 +148,7 @@ class DownloadActions extends Actions
|
|||
{
|
||||
//if exact OS is requested, use that
|
||||
$uri = strtok($_SERVER['REQUEST_URI'], '?');
|
||||
foreach (static::getOses() as $os => $osChoice)
|
||||
foreach (Os::getAll() as $os => $osChoice)
|
||||
{
|
||||
if ($osChoice[0] == $uri)
|
||||
{
|
||||
|
@ -182,67 +165,16 @@ class DownloadActions extends Actions
|
|||
$ua = $_SERVER['HTTP_USER_AGENT'];
|
||||
if (stripos($ua, 'OS X') !== false)
|
||||
{
|
||||
return strpos($ua, 'iPhone') !== false || stripos($ua, 'iPad') !== false ? static::OS_IOS : static::OS_OSX;
|
||||
return strpos($ua, 'iPhone') !== false || stripos($ua, 'iPad') !== false ? Os::OS_IOS : Os::OS_OSX;
|
||||
}
|
||||
if (stripos($ua, 'Linux') !== false || strpos($ua, 'X11') !== false)
|
||||
{
|
||||
return strpos($ua, 'Android') !== false ? static::OS_ANDROID : static::OS_LINUX;
|
||||
return strpos($ua, 'Android') !== false ? Os::OS_ANDROID : Os::OS_LINUX;
|
||||
}
|
||||
if (stripos($ua, 'Windows') !== false)
|
||||
{
|
||||
return static::OS_WINDOWS;
|
||||
return Os::OS_WINDOWS;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getDownloadUrl($os, $useCache = true)
|
||||
{
|
||||
if (!in_array($os, array_keys(static::getOses())))
|
||||
{
|
||||
throw new DomainException('Unknown OS');
|
||||
}
|
||||
|
||||
$apc = $useCache && extension_loaded('apc') && ini_get('apc.enabled');
|
||||
$key = 'lbry_release_data2';
|
||||
$releaseData = null;
|
||||
|
||||
if ($apc)
|
||||
{
|
||||
$releaseData = apc_fetch($key);
|
||||
}
|
||||
|
||||
if (!$releaseData)
|
||||
{
|
||||
try
|
||||
{
|
||||
$releaseData =
|
||||
json_decode(Curl::get('https://api.github.com/repos/lbryio/lbry/releases/latest', [], ['user_agent' => 'LBRY']), true);
|
||||
if ($apc)
|
||||
{
|
||||
apc_store($key, $releaseData, 600); // cache for 10 min
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (!$releaseData)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($releaseData['assets'] as $asset)
|
||||
{
|
||||
if (
|
||||
($os == static::OS_LINUX && in_array($asset['content_type'], ['application/x-debian-package', 'application/x-deb'])) ||
|
||||
($os == static::OS_OSX && in_array($asset['content_type'], ['application/x-diskcopy', 'application/x-apple-diskimage']))
|
||||
)
|
||||
{
|
||||
return $asset['browser_download_url'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class Curl
|
|||
'cache' => false,
|
||||
'headers' => [],
|
||||
'verify' => true,
|
||||
'timeout' => 5,
|
||||
'timeout' => 10, //5 was timing out on /roadmap for Asana API
|
||||
'follow_redirects' => true,
|
||||
'user_agent' => null,
|
||||
'proxy' => null,
|
||||
|
|
29
lib/tools/Os.class.php
Normal file
29
lib/tools/Os.class.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: kauffj
|
||||
* Date: 8/16/16
|
||||
* Time: 8:18 PM
|
||||
*/
|
||||
class Os
|
||||
{
|
||||
const OS_ANDROID = 'android',
|
||||
OS_IOS = 'ios',
|
||||
OS_LINUX = 'linux',
|
||||
OS_OSX = 'osx',
|
||||
OS_WINDOWS = 'windows';
|
||||
|
||||
public static function getAll()
|
||||
{
|
||||
//url, English name, icon class, partial name
|
||||
//yes, this is probably a bad pattern
|
||||
return [
|
||||
Os::OS_WINDOWS => ['/windows', 'Windows', 'icon-windows', '_windows'],
|
||||
Os::OS_OSX => ['/osx', 'OS X', 'icon-apple', '_osx'],
|
||||
Os::OS_LINUX => ['/linux', 'Linux', 'icon-linux', '_linux'],
|
||||
Os::OS_ANDROID => ['/android', 'Android', 'icon-android', '_android'],
|
||||
Os::OS_IOS => ['/ios', 'iOS', 'icon-mobile', '_ios']
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Description of CreditApi
|
||||
*
|
||||
* @author jeremy
|
||||
*/
|
||||
class CreditApi
|
||||
{
|
||||
public static function getCurrentTestCreditReward()
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public static function getTotalDollarSales()
|
||||
{
|
||||
return 22585;
|
||||
}
|
||||
|
||||
public static function getTotalPeople()
|
||||
{
|
||||
$rawJSON = @file_get_contents('https://spreadsheets.google.com/feeds/cells/1iOC1o5jq_4ySwRzsy2tZPPltw6Tbky2e3lDFdsWV8dU/okf1n52/public/full/R1C1?alt=json');
|
||||
$json = $rawJSON ? json_decode($rawJSON, true) : [];
|
||||
return isset($json['entry']) && isset($json['entry']['content']) && is_numeric($json['entry']['content']['$t'] ) ?
|
||||
$json['entry']['content']['$t'] :
|
||||
6687; //fallback #
|
||||
}
|
||||
|
||||
public static function getCreditsPerDollar($days)
|
||||
{
|
||||
//naive algo = decrease 0.5% per day
|
||||
return 200 * max(0, 100 - $days / 2) / 100;
|
||||
}
|
||||
}
|
|
@ -53,13 +53,13 @@ class Asana
|
|||
*/
|
||||
// return static::get('/projects');
|
||||
$projects = [
|
||||
158602294500138 => 'LBRY Browser',
|
||||
158602294500137 => 'LBRYnet',
|
||||
161514803479899 => 'Blockchain and Wallets',
|
||||
158829550589337 => 'Reporting and Analytics',
|
||||
136290697597644 => 'Integration and Building',
|
||||
158602294500249 => 'Documentation',
|
||||
158602294500214 => 'Other'
|
||||
158602294500138 => ['LBRY Browser', 'https://github.com/lbryio/lbry-web-ui'],
|
||||
158602294500137 => ['LBRYnet', 'https://github.com/lbryio/lbry'],
|
||||
161514803479899 => ['Blockchain and Wallets', 'https://github.com/lbryio/lbrycrd'],
|
||||
158829550589337 => ['Reporting and Analytics', null],
|
||||
136290697597644 => ['Integration and Building', null],
|
||||
158602294500249 => ['Documentation', null],
|
||||
158602294500214 => ['Other', null]
|
||||
];
|
||||
|
||||
$tasks = [
|
||||
|
@ -68,8 +68,9 @@ class Asana
|
|||
];
|
||||
|
||||
$categories = array_keys($tasks);
|
||||
foreach($projects as $projectId => $projectName)
|
||||
foreach($projects as $projectId => $projectTuple)
|
||||
{
|
||||
list($projectName, $projectUrl) = $projectTuple;
|
||||
$projectTasks = static::get('/tasks?' . http_build_query(['completed_since' => 'now', 'project' => $projectId]));
|
||||
$key = null;
|
||||
foreach ($projectTasks as $task)
|
||||
|
@ -85,20 +86,30 @@ class Asana
|
|||
$fullTask = static::get('/tasks/' . $task['id']);
|
||||
$tasks[$key][] = array_intersect_key($fullTask, ['name' => null, 'due_on' => null]) + [
|
||||
'project' => $projectName,
|
||||
'url' => $projectUrl,
|
||||
'assignee' => $fullTask['assignee'] ? ucwords($fullTask['assignee']['name']) : ''
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($tasks as &$taskSet)
|
||||
{
|
||||
usort($taskSet, function($tA, $tB) {
|
||||
if ($tA['due_on'] xor $tB['due_on'])
|
||||
{
|
||||
return $tA['due_on'] ? -1 : 1;
|
||||
}
|
||||
return $tA['due_on'] < $tB['due_on'] ? -1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
|
||||
protected static function get($endpoint, array $data = [])
|
||||
{
|
||||
$apiKey = '0/c85cfce3591c2a3e214408cfba7cc44c';
|
||||
// $apiKey = Config::get('prefinery_key');
|
||||
// curl -H "Authorization: Bearer ACCESS_TOKEN" https://app.asana.com/api/1.0/users/me
|
||||
$apiKey = Config::get('asana_key');
|
||||
|
||||
$options = static::$curlOptions + [
|
||||
'headers' => ['Authorization: Bearer ' . $apiKey]
|
71
model/api/Github.class.php
Normal file
71
model/api/Github.class.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
class Github
|
||||
{
|
||||
public static function getDownloadUrl($os, $useCache = true)
|
||||
{
|
||||
if (!in_array($os, array_keys(Os::getAll())))
|
||||
{
|
||||
throw new DomainException('Unknown OS');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$releaseData = static::get('/repos/lbryio/lbry/releases/latest');
|
||||
foreach ($releaseData['assets'] as $asset)
|
||||
{
|
||||
if (
|
||||
($os == Os::OS_LINUX && in_array($asset['content_type'], ['application/x-debian-package', 'application/x-deb'])) ||
|
||||
($os == Os::OS_OSX && in_array($asset['content_type'], ['application/x-diskcopy', 'application/x-apple-diskimage']))
|
||||
)
|
||||
{
|
||||
return $asset['browser_download_url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function get($endpoint)
|
||||
{
|
||||
return Curl::get('https://api.github.com' . $endpoint, [], ['user_agent' => 'LBRY', 'json_response' => true, 'cache' => false]);
|
||||
}
|
||||
|
||||
public static function listRoadmapChangesets()
|
||||
{
|
||||
$sets = [];
|
||||
|
||||
$page = 1;
|
||||
$allReleases = [];
|
||||
|
||||
do
|
||||
{
|
||||
$releases = static::get('/repos/lbryio/lbry/releases?page=' . $page);
|
||||
$page++;
|
||||
$allReleases = array_merge($allReleases, $releases);
|
||||
} while (count($releases) >= 30);
|
||||
|
||||
usort($allReleases, function($rA, $rB) {
|
||||
if ($rA['prerelease'] xor $rB['prerelease'])
|
||||
{
|
||||
return $rA['prerelease'] ? -1 : 1;
|
||||
}
|
||||
return $rA['tag_name'] < $rB['tag_name'];
|
||||
});
|
||||
|
||||
foreach($allReleases as $release)
|
||||
{
|
||||
// static::get('/repos/lbryio/lbry/releases')
|
||||
$sets[$release['tag_name']] = array_intersect_key($release, ['prerelease' => null]) + [
|
||||
'published_at' => date('Y-m-d', strtotime($release['published_at'])),
|
||||
'body' => ParsedownExtra::instance()->text($release['body'])
|
||||
];
|
||||
}
|
||||
|
||||
return $sets;
|
||||
}
|
||||
}
|
|
@ -3,27 +3,77 @@
|
|||
<?php echo View::render('nav/_header', ['isDark' => false]) ?>
|
||||
|
||||
<main>
|
||||
<div class="content content-light">
|
||||
<div class="content content-light spacer2">
|
||||
<h1>{{roadmap.title}}</h1>
|
||||
<div class="help">
|
||||
The LBRY roadmap pulls in information dynamically from our internal project management system and public
|
||||
<a href="https://github.com/lbryio" class="link-primary">GitHub</a> page.
|
||||
<div class="help spacer2">
|
||||
Recent, ongoing and upcoming changes to LBRY.
|
||||
</div>
|
||||
<h2>Scheduled Changes</h2>
|
||||
<?php foreach($tasks as $category => $categoryTasks): ?>
|
||||
<section>
|
||||
<h3><?php echo ucfirst($category) ?></h3>
|
||||
<table class="content full-table">
|
||||
<?php foreach($categoryTasks as $task): ?>
|
||||
<tr>
|
||||
<td><?php echo $task['name'] ?></td>
|
||||
<td style="width: 20%"><?php echo $task['project'] ?></td>
|
||||
<td style="width: 15%"><?php echo $task['due_on'] ?></td>
|
||||
<td style="width: 20%"><?php echo $task['assignee'] ?></td>
|
||||
<section class="spacer2">
|
||||
<h2>Recent Changes</h2>
|
||||
<table class="content full-table" id="changeset-table">
|
||||
<?php $setCount = 0 ?>
|
||||
<thead>
|
||||
<th>Release</th>
|
||||
<th>Date</th>
|
||||
<th>Notes</th>
|
||||
</thead>
|
||||
<?php foreach($changesets as $version => $changeset): ?>
|
||||
<tr <?php echo ++$setCount > 5 ? 'style="display: none"' : '' ?>>
|
||||
<th style="width: 15%">
|
||||
<?php echo $version ?>
|
||||
<?php if ($changeset['prerelease']): ?>
|
||||
<span class="badge badge-info">prerelease</span>
|
||||
<?php endif ?>
|
||||
</th>
|
||||
<td style="width: 15%" class="center"><?php echo $changeset['published_at'] ?></td>
|
||||
<td><?php echo $changeset['body'] ?></td>
|
||||
</tr>
|
||||
<?php if ($version == 'v0.2.2'): ?>
|
||||
<tr style="display: none">
|
||||
<th>v0.1-v0.2.2</th>
|
||||
<td></td>
|
||||
<td>These releases were not tagged and noted properly. We were too busy creating awesome!</td>
|
||||
</tr>
|
||||
<?php endif ?>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
<a href="javascript:;" class="link-primary" id="show-all-changesets">show all changes</a>
|
||||
<?php js_start() ?>
|
||||
$('#show-all-changesets').click(function() {
|
||||
$(this).hide();
|
||||
$('#changeset-table').find('tr').show();
|
||||
});
|
||||
<?php js_end() ?>
|
||||
</section>
|
||||
<?php foreach($tasks as $category => $categoryTasks): ?>
|
||||
<section class="spacer2">
|
||||
<h2><?php echo ucfirst($category) ?> Changes</h2>
|
||||
<table class="content full-table">
|
||||
<thead>
|
||||
<th>Item</th>
|
||||
<th>Date</th>
|
||||
<th>Component</th>
|
||||
<th>Owner</th>
|
||||
</thead>
|
||||
<?php foreach($categoryTasks as $task): ?>
|
||||
<tr>
|
||||
<td><?php echo $task['name'] ?></td>
|
||||
<td style="width: 15%"><?php echo $task['due_on'] ?></td>
|
||||
<td style="width: 20%">
|
||||
<?php if ($task['url']): ?>
|
||||
<a href="<?php echo $task['url'] ?>" class="link-primary"><?php echo $task['project'] ?></a>
|
||||
<?php else: ?>
|
||||
<?php echo $task['project'] ?>
|
||||
<?php endif ?>
|
||||
</td>
|
||||
<td style="width: 20%">
|
||||
<?php echo $task['assignee'] ?: '<em>unassigned</em>' ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
</section>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
</main>
|
||||
</main>
|
||||
<?php echo View::render('nav/_footer') ?>
|
|
@ -1,8 +1,8 @@
|
|||
<div class="notice notice-info">
|
||||
<p>{{download.unavailable}}</p>
|
||||
<?php if ($os == DownloadActions::OS_OSX): ?>
|
||||
<?php if ($os == Os::OS_OSX): ?>
|
||||
<p>{{download.osx}}</p>
|
||||
<?php elseif ($os == DownloadActions::OS_WINDOWS): ?>
|
||||
<?php elseif ($os == Os::OS_WINDOWS): ?>
|
||||
<p>{{download.windows}}</p>
|
||||
<?php endif ?>
|
||||
</div>
|
|
@ -18,4 +18,8 @@ $badge-height: $spacing-vertical * 3/4;
|
|||
{
|
||||
background-color: $color-primary;
|
||||
}
|
||||
&.badge-info
|
||||
{
|
||||
background-color: $color-info-bg;
|
||||
}
|
||||
}
|
|
@ -138,6 +138,10 @@
|
|||
vertical-align: text-bottom;
|
||||
}
|
||||
}
|
||||
td.center
|
||||
{
|
||||
vertical-align: middle;
|
||||
}
|
||||
tr.thead:not(:first-child) th
|
||||
{
|
||||
border-top: 1px solid #e2e2e2;
|
||||
|
|
|
@ -7,6 +7,7 @@ $color-light-alt: hsl(hue($color-primary), 15, 85);
|
|||
$color-text-dark: #000;
|
||||
$color-money: #216C2A;
|
||||
$color-meta-light: #505050;
|
||||
$color-info-bg: #3a779d;
|
||||
|
||||
$font-size: 16px;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue