added GitHub API support (show release info)

new dialog (show release info)
fixed caching timings (main ajax update trigger calls)
fixed footer "current year" number
This commit is contained in:
Exodus4D
2016-01-16 15:09:58 +01:00
parent 6bf0a1aa77
commit 3f4d33a3a9
29 changed files with 459 additions and 84 deletions

View File

@@ -0,0 +1,82 @@
<?php
/**
* Created by PhpStorm.
* User: exodus4d
* Date: 16.01.16
* Time: 03:34
*/
namespace Controller\Api;
use Model;
use Controller;
/**
* Github controller
* Class Route
* @package Controller\Api
*/
class GitHub extends Controller\Controller {
/**
* get HTTP request options for API (curl) request
* @return array
*/
protected function getRequestOptions(){
$requestOptions = [
'timeout' => 8,
'method' => 'GET',
'user_agent' => $this->getUserAgent(),
'follow_location' => false // otherwise CURLOPT_FOLLOWLOCATION will fail
];
return $requestOptions;
}
/**
* get release information from GitHub
* @param $f3
*/
public function releases($f3){
$cacheKey = 'CACHE_GITHUB_RELEASES';
$ttl = 60 * 30; // 30min
$releaseCount = 5;
if( !$f3->exists($cacheKey) ){
$apiPath = $this->getF3()->get('PATHFINDER.API.GIT_HUB') . '/repos/exodus4d/pathfinder/releases';
// build request URL
$options = $this->getRequestOptions();
$apiResponse = \Web::instance()->request($apiPath, $options );
if($apiResponse['body']){
// request succeeded -> format "Markdown" to "HTML"
// result is JSON formed
$releasesData = (array)json_decode($apiResponse['body']);
// check max release count
if(count($releasesData) > $releaseCount){
$releasesData = array_slice($releasesData, 0, $releaseCount);
}
$md = \Markdown::instance();
foreach($releasesData as &$releaseData){
if(isset($releaseData->body)){
$releaseData->body = $md->convert( $releaseData->body );
}
}
$f3->set($cacheKey, $releasesData, $ttl);
}else{
// request failed -> cache failed result (respect API request limit)
$f3->set($cacheKey, false, 60 * 5);
}
}
// set 503 if service unavailable or temp cached data = false
if( !$f3->get($cacheKey) ){
$f3->status(503);
}
echo json_encode($f3->get($cacheKey));
}
}

View File

@@ -465,7 +465,7 @@ class Map extends \Controller\AccessController {
$responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_MAP.DELAY') / 1000;
$mapData = (array)$f3->get('POST.mapData');
$user = $this->_getUser(0);
$user = $this->_getUser();
$return = (object) [];
$return->error = [];
@@ -628,7 +628,7 @@ class Map extends \Controller\AccessController {
$return = (object) [];
$return->error = [];
$user = $this->_getUser(0);
$user = $this->_getUser();
if($user){

View File

@@ -16,22 +16,6 @@ use Model;
*/
class CcpApiController extends Controller{
/**
* get a custom userAgent string for API calls
* (recommended by CCP)
* @return string
*/
protected function getUserAgent(){
$userAgent = '';
$userAgent .= $this->getF3()->get('PATHFINDER.NAME');
$userAgent .= ' - ' . $this->getF3()->get('PATHFINDER.VERSION');
$userAgent .= ' | ' . $this->getF3()->get('PATHFINDER.CONTACT');
$userAgent .= ' (' . $_SERVER['SERVER_NAME'] . ')';
return $userAgent;
}
/**
* get HTTP request options for API (curl) request
* @return array

View File

@@ -434,6 +434,21 @@ class Controller {
return $url;
}
/**
* get a custom userAgent string for API calls
* @return string
*/
protected function getUserAgent(){
$userAgent = '';
$userAgent .= $this->getF3()->get('PATHFINDER.NAME');
$userAgent .= ' - ' . $this->getF3()->get('PATHFINDER.VERSION');
$userAgent .= ' | ' . $this->getF3()->get('PATHFINDER.CONTACT');
$userAgent .= ' (' . $_SERVER['SERVER_NAME'] . ')';
return $userAgent;
}
/**
* onError() callback function
* -> on AJAX request -> return JSON with error information
@@ -475,6 +490,7 @@ class Controller {
if($f3->get('AJAX')){
header('Content-type: application/json');
echo json_encode($return);
die();
}else{
// set error data for template rendering
$error->redirectUrl = $this->getRouteUrl();

View File

@@ -104,3 +104,4 @@ DELETE_ACCOUNT = delete_account
[PATHFINDER.API]
; Path for CCPs XML APIv2
CCP_XML = https://api.eveonline.com
GIT_HUB = https://api.github.com

View File

@@ -43,7 +43,9 @@ define(['jquery'], function($) {
saveSignatureData: 'api/signature/save', // ajax URL - save signature data for system
deleteSignatureData: 'api/signature/delete', // ajax URL - delete signature data for system
// route API
searchRoute: 'api/route/search' // ajax URL - search system routes
searchRoute: 'api/route/search', // ajax URL - search system routes
// GitHub API
gitHubReleases: 'api/github/releases' // ajax URL - get release info from GitHub
},
url: {
ccpImageServer: 'https://image.eveonline.com/', // CCP image Server

View File

@@ -17,6 +17,7 @@ define([
'dialog/account_settings',
'dialog/notification',
'dialog/manual',
'dialog/releases',
'dialog/credit'
], function($, Init, Util, Render, CCP, Gallery, bootbox) {
@@ -39,7 +40,8 @@ define([
// navigation
navigationElementId: 'pf-navbar', // id for navbar element
navigationLinkManualClass: 'pf-navbar-manual', // class for "manual" trigger link
navigationLinkLicenseClass : 'pf-navbar-license', // class for "license" trigger link
navigationLinkLicenseClass: 'pf-navbar-license', // class for "license" trigger link
navigationVersionLinkClass: 'pf-navbar-version-info', // class for "version information"
// login form
loginFormId: 'pf-login-form', // id for login form
@@ -130,6 +132,11 @@ define([
}
});
// releases -----------------------------------------------------
$('.' + config.navigationVersionLinkClass).on('click', function(e){
$.fn.releasesDialog();
});
// manual -------------------------------------------------------
$('.' + config.navigationLinkManualClass).on('click', function(e){
e.preventDefault();

View File

@@ -481,7 +481,8 @@ define([
var moduleData = {
id: config.pageFooterId,
footerLicenceLinkClass: config.footerLicenceLinkClass
footerLicenceLinkClass: config.footerLicenceLinkClass,
currentYear: new Date().getFullYear()
};
var headRendered = Mustache.render(TplFooter, moduleData);

View File

@@ -0,0 +1,80 @@
/**
* releases dialog (GitHub API repository information)
*/
define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox'
], function($, Init, Util, Render, bootbox) {
'use strict';
var config = {
releasesDialogClass: 'pf-releases-dialog' // class for "Releases" dialog
};
/**
* load release information in dialog
* @param releasesDialog
*/
var loadDialogData = function(releasesDialog){
$.ajax({
type: 'POST',
url: Init.path.gitHubReleases,
// data: updatedMapData,
dataType: 'json'
}).done(function(releasesData){
requirejs(['text!templates/ui/timeline_element.html', 'mustache'], function(template, Mustache) {
for(var i = 0; i < releasesData.length; i++){
var releaseData = releasesData[i];
// template vars
var data = {
isFirst: (i === 0),
isOdd: (i % 2 !== 0),
releaseDate: releaseData.published_at.substr(0, 10),
releaseData: releaseData
};
var content = Mustache.render(template, data);
releasesDialog.find('ul.timeline').append(content);
}
});
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + jqXHR.status + ': ' + error;
Util.showNotify({title: jqXHR.status + ': login', text: reason, type: 'error'});
});
};
/**
* show releases dialog
*/
$.fn.releasesDialog = function(){
requirejs(['text!templates/dialog/releases.html', 'mustache'], function(template, Mustache) {
var data = {
test: 'blaBla'
};
var content = Mustache.render(template, data);
var releasesDialog = bootbox.dialog({
className: config.releasesDialogClass,
title: 'Releases',
size: 'large',
message: content
});
// after modal is shown =======================================================================
releasesDialog.on('shown.bs.modal', function(e) {
loadDialogData(releasesDialog);
});
});
};
});

View File

@@ -72,7 +72,7 @@ define([
}
},
trust: {
label: '<i class="fa fa-fw fa-lock"></i> trust set',
label: '<i class="fa fa-fw fa-lock"></i> set "Trust"',
className: 'btn-primary',
callback: function(){
var dialog = $(this);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -96,6 +96,7 @@ app/ui/demo_map.js
app/ui/dialog/account_settings.js
app/ui/dialog/notification.js
app/ui/dialog/manual.js
app/ui/dialog/releases.js
app/ui/dialog/credit.js
app/landingpage.js
lib/requirejs/text.js

View File

@@ -0,0 +1,2 @@
<ul class="timeline"></ul>

View File

@@ -3,7 +3,7 @@
<div class="navbar-header pull-left">
<p class="navbar-text txt-color txt-color-gray"><i class="fa fa-copyright"></i>
2015 <a class="{{footerLicenceLinkClass}}" href="javascript:void(0)" target="_blank">Licence</a>
{{ currentYear }} <a class="{{footerLicenceLinkClass}}" href="javascript:void(0)" target="_blank">Licence</a>
</p>
</div>
<div class="navbar-header pull-right">

View File

@@ -0,0 +1,19 @@
<li class="{{#isOdd}}timeline-inverted{{/isOdd}} {{#isFirst}}timeline-first{{/isFirst}}">
<div class="timeline-badge"><i class="fa fa-lg fa-github fa-fw"></i></div>
<div class="timeline-panel">
<div class="timeline-heading">
<h4 class="timeline-title">
<a href="{{releaseData.html_url}}" target="_blank">{{ releaseData.name }}</a>
<span class="text-muted pull-right">
{{ #releaseData.prerelease }}
<span class="label label-danger">Pre-release</span>
{{ /releaseData.prerelease }}
<i class="fa fa-calendar fa-fw"></i> {{ releaseDate }}
</span>
</h4>
<p><small class="text-muted"></small></p>
</div>
<div class="timeline-body">{{{ releaseData.body }}}</div>
</div>
</li>

View File

@@ -18,7 +18,7 @@
</button>
<p class="navbar-text">
<span class="badge txt-color txt-color-grayLight">{{ @PATHFINDER.VERSION }}</span>
<span class="badge txt-color txt-color-green pf-navbar-version-info">{{ @PATHFINDER.VERSION }}</span>
</p>
<ul class="nav navbar-nav navbar-right" role="tablist">
@@ -130,6 +130,7 @@
</div>
</check>
{* signUp/logIn buttons *}
<div class="row text-center">
<div class="col-sm-6 col-sm-offset-3">
<div class="col-xs-6 col-sm-4 col-sm-offset-2" data-placement="left" title="{{@registrationStatusTitle}}">
@@ -145,6 +146,8 @@
</section>
{* features/ gallery *}
<section id="pf-landing-gallery">
@@ -823,6 +826,7 @@
<p>
Unfortunately not. I will probably not have the time to answer any question personally.
Make sure you have read the <span class="pf-navbar-manual"><a href="javascript:void(0);">manual</a></span>.
<br>
If there are still some open questions, please ask in the <a target="_blank" href="https://forums.eveonline.com/">official forums</a> thread for help.
</p>
<h3>Which browsers are compatible with <em>Pathfinder</em>?</h3>

View File

@@ -728,14 +728,14 @@ $close-text-shadow: 0 1px 0 #fff;
//
//##
$code-color: #c7254e;
$code-bg: #f9f2f4;
$code-color: $gray-darkest;
$code-bg: $gray-light;
$kbd-color: $gray-lighter;
$kbd-bg: $gray-darker;
$pre-bg: #f5f5f5;
$pre-color: $gray-dark;
$pre-bg: $gray-light;
$pre-color: $gray-darkest;
$pre-border-color: #ccc;
$pre-scrollable-max-height: 340px;

View File

@@ -18,7 +18,7 @@ code {
color: $code-color;
background-color: $code-bg;
white-space: nowrap;
border-radius: $border-radius-base;
border-radius: $border-radius-small;
}
// User input typically entered via keyboard
@@ -42,8 +42,8 @@ pre {
word-wrap: break-word;
color: $pre-color;
background-color: $pre-bg;
border: 1px solid $pre-border-color;
border-radius: $border-radius-base;
// border: 1px solid $pre-border-color;
border-radius: $border-radius-small;
// Account for some code outputs that place code tags in pre tags
code {

View File

@@ -8,6 +8,7 @@
@import "_dialogs";
@import "_log";
@import "_animation";
@import "_timeline";
@import "_ribbon";
@import "_loading-bar";
@import "_youtube";

View File

@@ -257,29 +257,35 @@ table{
}
// navbar li ====================================================
.navbar-nav li{
.navbar-nav {
li{
&:hover, &.active{
&:hover, &.active{
&:before{
top: -4px;
opacity: 1;
}
}
&:before{
top: -4px;
opacity: 1;
content: '';
position: absolute;
width: 100%;
height: 2px;
background-color: $green;
top: 0;
opacity: 0;
will-change: opacity, top;
@include transition( top 0.15s ease-out, opacity 0.15s ease-out );
}
}
}
&:before{
content: '';
position: absolute;
width: 100%;
height: 2px;
background-color: $green;
top: 0;
opacity: 0;
will-change: opacity, top;
@include transition( top 0.15s ease-out, opacity 0.15s ease-out );
}
.pf-navbar-version-info{
cursor: pointer;
}
// page menu =====================================================

169
sass/layout/_timeline.scss Normal file
View File

@@ -0,0 +1,169 @@
.timeline {
list-style: none;
position: relative;
}
.timeline:before {
top: 0;
bottom: 0;
position: absolute;
content: " ";
width: 1px;
// background-color: $gray-light;
left: 50%;
margin-top: 20px;
@include background-image(linear-gradient(to bottom, $green-dark, $gray-light 25%));
}
.timeline > li {
margin-bottom: 20px;
position: relative;
&.timeline-first{
.timeline-title{
color: $green-dark;
}
.timeline-badge{
background-color: $green-dark;
}
}
}
.timeline > li:before,
.timeline > li:after {
content: " ";
display: table;
}
.timeline > li:after {
clear: both;
}
.timeline > li:before,
.timeline > li:after {
content: " ";
display: table;
}
.timeline > li:after {
clear: both;
}
.timeline > li > .timeline-panel {
width: 47%;
float: left;
border: 1px solid $gray-dark;
padding: 8px;
position: relative;
background-color: $gray-dark;
@include box-shadow(0 4px 10px rgba(0,0,0, 0.4));
@include border-radius(5px);
}
.timeline > li > .timeline-panel:before {
content: " ";
position: absolute;
top: 10px;
right: -8px;
display: inline-block;
border-top: 7px solid transparent;
border-left: 7px solid $gray-light;
border-right: 0 solid $gray-light;
border-bottom: 7px solid transparent;
}
.timeline > li > .timeline-panel:after {
content: " ";
position: absolute;
top: 10px;
right: -8px;
display: inline-block;
border-top: 7px solid transparent;
border-left: 7px solid $gray-light;
border-right: 0 solid $gray-light;
border-bottom: 7px solid transparent;
}
.timeline > li > .timeline-badge {
color: $gray-darker;
width: 22px;
height: 22px;
line-height: 22px;
text-align: center;
position: absolute;
top: 7px;
left: 50%;
margin-left: -11px;
background-color: $gray-light;
z-index: 100;
@include border-radius(50%);
}
.timeline > li.timeline-inverted > .timeline-panel {
float: right;
}
.timeline > li.timeline-inverted > .timeline-panel:before {
border-left-width: 0;
border-right-width: 7px;
left: -8px;
right: auto;
}
.timeline > li.timeline-inverted > .timeline-panel:after {
border-left-width: 0;
border-right-width: 8px;
left: -9px;
right: auto;
}
.timeline-title {
margin-top: 0;
color: inherit;
}
.timeline-body > p,
.timeline-body > ul {
margin-bottom: 0;
}
.timeline-body > p + p {
margin-top: 5px;
}
@media (max-width: 1200px) {
ul.timeline:before {
left: 40px;
}
ul.timeline > li > .timeline-panel {
width: calc(100% - 62px);
}
ul.timeline > li > .timeline-badge {
left: 29px;
margin-left: 0;
top: 6px;
}
ul.timeline > li > .timeline-panel {
float: right;
}
ul.timeline > li > .timeline-panel:before {
border-left-width: 0;
border-right-width: 7px;
left: -8px;
right: auto;
}
ul.timeline > li > .timeline-panel:after {
border-left-width: 0;
border-right-width: 7px;
left: -8px;
right: auto;
}
}