diff --git a/app/main/controller/api/github.php b/app/main/controller/api/github.php index 974ed3da..8f76a013 100644 --- a/app/main/controller/api/github.php +++ b/app/main/controller/api/github.php @@ -52,6 +52,14 @@ class GitHub extends Controller\Controller { $apiResponse = \Web::instance()->request($apiPath, $options ); if($apiResponse['body']){ + $return = (object) []; + $return->releasesData = []; + $return->version = (object) []; + $return->version->current = Config::getPathfinderData('version'); + $return->version->last = ''; + $return->version->delta = null; + $return->version->dev = false; + // request succeeded -> format "Markdown" to "HTML" // result is JSON formed $releasesData = (array)json_decode($apiResponse['body']); @@ -62,7 +70,24 @@ class GitHub extends Controller\Controller { } $md = \Markdown::instance(); - foreach($releasesData as &$releaseData){ + foreach($releasesData as $key => &$releaseData){ + // check version ---------------------------------------------------------------------------------- + if($key === 0){ + $return->version->last = $releaseData->tag_name; + + if(version_compare( $return->version->current, $return->version->last, '>')){ + $return->version->dev = true; + } + } + + if( + !$return->version->dev && + version_compare( $releaseData->tag_name, $return->version->current, '>=') + ){ + $return->version->delta = ($key === count($releasesData) - 1) ? '>= ' . $key : $key; + } + + // format body ------------------------------------------------------------------------------------ if(isset($releaseData->body)){ $body = $releaseData->body; @@ -78,7 +103,10 @@ class GitHub extends Controller\Controller { $releaseData->body = $md->convert( trim($body) ); } } - $f3->set($cacheKey, $releasesData, $ttl); + + $return->releasesData = $releasesData; + + $f3->set($cacheKey, $return, $ttl); }else{ // request failed -> cache failed result (respect API request limit) $f3->set($cacheKey, false, 60 * 5); diff --git a/js/app/login.js b/js/app/login.js index 82d87079..874afd89 100644 --- a/js/app/login.js +++ b/js/app/login.js @@ -16,7 +16,7 @@ define([ 'dialog/account_settings', 'dialog/notification', 'dialog/manual', - 'dialog/releases', + 'dialog/changelog', 'dialog/credit' ], function($, Init, Util, Render, Gallery, bootbox) { @@ -81,7 +81,7 @@ define([ */ let setVersionLinkObserver = function(){ $('.' + config.navigationVersionLinkClass).off('click').on('click', function(e){ - $.fn.releasesDialog(); + $.fn.changelogsDialog(); }); }; diff --git a/js/app/ui/dialog/changelog.js b/js/app/ui/dialog/changelog.js new file mode 100644 index 00000000..f84188de --- /dev/null +++ b/js/app/ui/dialog/changelog.js @@ -0,0 +1,140 @@ +/** + * changelog dialog (GitHub API repository information) + */ + +define([ + 'jquery', + 'app/init', + 'app/util', + 'app/render', + 'bootbox' +], ($, Init, Util, Render, bootbox) => { + 'use strict'; + + let config = { + changelogDialogClass: 'pf-changelog-dialog', // class for "changelog" dialog + dynamicMessageContainerClass: 'pf-dynamic-message-container', // class for "dynamic" (JS) message container + timelineClass: 'timeline' // class for "timeline" + + }; + + /** + * show version information + * @param changelogDialog + * @param versionData + */ + let showVersion = (changelogDialog, versionData) => { + let type = 'error'; + let title = versionData.current; + let text = 'Installed version check failed'; + + if(versionData.dev){ + // developer version + type = 'info'; + title = versionData.current + ' (dev)'; + text = 'This installation is ahead of current stable version ' + versionData.last + '.'; + }else{ + // standard version + if(versionData.delta === 0){ + // last stable + type = 'success'; + title = versionData.current; + text = 'This installation is up2date.'; + }else{ + // outdated... + type = 'warning'; + title = versionData.current; + text = 'This installation is ' + versionData.delta + ' version behind current stable ' + versionData.last + '.'; + } + } + + changelogDialog.find('.' + config.dynamicMessageContainerClass).showMessage({ + dismissible: false, + type: type, + title: title, + text: text + }); + }; + + /** + * load changelog information in dialog + * @param changelogDialog + */ + let loadDialogData = (changelogDialog) => { + + // lock dialog + let dialogContent = changelogDialog.find('.modal-content'); + dialogContent.showLoadingAnimation(); + + $.ajax({ + type: 'POST', + url: Init.path.gitHubReleases, + dataType: 'json', + context: { + changelogDialog: changelogDialog + } + }).done(function(data){ + let changelogDialog = this.changelogDialog; + let versionData = data.version; + let releasesData = data.releasesData; + + showVersion(changelogDialog, versionData); + + requirejs(['text!templates/ui/timeline_element.html', 'mustache'], function(template, Mustache) { + for(let i = 0; i < releasesData.length; i++){ + let releaseData = releasesData[i]; + + // template vars + let data = { + isFirst: (i === 0), + isOdd: (i % 2 !== 0), + releaseDate: releaseData.published_at.substr(0, 10), + releaseData: releaseData + }; + + let content = Mustache.render(template, data); + changelogDialog.find('ul.' + config.timelineClass).append(content); + } + + changelogDialog.find('.timeline > li').velocity('transition.expandIn', { + stagger: 300, + duration: 240, + //display: 'auto', + complete: function(){} + }); + }); + }).fail(function( jqXHR, status, error) { + let reason = status + ' ' + jqXHR.status + ': ' + error; + Util.showNotify({title: jqXHR.status + ': login', text: reason, type: 'error'}); + }).always(function() { + dialogContent.hideLoadingAnimation(); + }); + }; + + /** + * show changelog dialog + */ + $.fn.changelogsDialog = function(){ + let content = $('
').append( + $('
', { + class: config.dynamicMessageContainerClass + }), + $('