mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-01-17 13:18:21 +01:00
Implement a basic update check in the system settings (#96)
This commit is contained in:
parent
b6b6f57ad8
commit
54226a5eca
60
app/Helper/UpdateHelper.php
Normal file
60
app/Helper/UpdateHelper.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use Composer\Semver\Comparator;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
/**
|
||||
* Class UpdateHelper
|
||||
*
|
||||
* @package App\Helper
|
||||
*/
|
||||
class UpdateHelper
|
||||
{
|
||||
protected static $releaseApiUrl = 'https://api.github.com/repos/kovah/linkace/releases';
|
||||
|
||||
/**
|
||||
* Returns the version string if there is a newer version is available.
|
||||
* Returns true if the check was successful, but no updates was found.
|
||||
* Returns false if the check could not be executed, e.g. due to network
|
||||
* issues.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function checkForUpdates()
|
||||
{
|
||||
$currentVersion = config('linkace.version');
|
||||
$latestVersion = self::getCurrentVersionFromAPI();
|
||||
|
||||
if ($latestVersion === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Comparator::greaterThan($latestVersion, $currentVersion)) {
|
||||
return $latestVersion;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* We try to get the latest releases from the Github API and then get the
|
||||
* tag name from the latest. If the request failed for some reason or no
|
||||
* release could be found, null is returned.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function getCurrentVersionFromAPI(): ?string
|
||||
{
|
||||
$response = Http::get(self::$releaseApiUrl);
|
||||
|
||||
if (!$response->successful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$releases = $response->json();
|
||||
|
||||
return $releases[0]['tag_name'] ?? null;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helper\UpdateHelper;
|
||||
use App\Models\Link;
|
||||
use App\Models\LinkList;
|
||||
use App\Models\Tag;
|
||||
@ -76,4 +77,11 @@ class FetchController extends Controller
|
||||
|
||||
return response()->json(['linkFound' => $linkCount > 0]);
|
||||
}
|
||||
|
||||
public static function checkForUpdates(): JsonResponse
|
||||
{
|
||||
$updateCheck = UpdateHelper::checkForUpdates();
|
||||
|
||||
return response()->json(['checkResult' => $updateCheck]);
|
||||
}
|
||||
}
|
||||
|
2
resources/assets/js/app.js
vendored
2
resources/assets/js/app.js
vendored
@ -9,6 +9,7 @@ import SimpleSelect from './components/SimpleSelect';
|
||||
import ShareToggleAll from './components/ShareToggleAll';
|
||||
import GenerateApiToken from './components/GenerateApiToken';
|
||||
import GenerateCronToken from './components/GenerateCronToken';
|
||||
import UpdateCheck from './components/UpdateCheck';
|
||||
|
||||
// Register view components
|
||||
function registerViews () {
|
||||
@ -21,6 +22,7 @@ function registerViews () {
|
||||
register('.share-toggle', ShareToggleAll);
|
||||
register('.api-token', GenerateApiToken);
|
||||
register('.cron-token', GenerateCronToken);
|
||||
register('.update-check', UpdateCheck);
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
|
51
resources/assets/js/components/UpdateCheck.js
vendored
Normal file
51
resources/assets/js/components/UpdateCheck.js
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
import { debounce } from '../lib/helper';
|
||||
|
||||
export default class UpdateCheck {
|
||||
|
||||
constructor ($el) {
|
||||
this.result = null;
|
||||
|
||||
this.$el = $el;
|
||||
this.$running = $el.querySelector('.update-check-running');
|
||||
this.$versionFound = $el.querySelector('.update-check-version-found');
|
||||
this.$success = $el.querySelector('.update-check-success');
|
||||
this.$failed = $el.querySelector('.update-check-failed');
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init () {
|
||||
debounce(() => {
|
||||
this.checkForUpdate().then(result => {
|
||||
this.result = result;
|
||||
this.updateCheckStatus();
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
updateCheckStatus () {
|
||||
this.$running.classList.add('d-none');
|
||||
|
||||
if (typeof this.result.length === 'string') {
|
||||
this.$versionFound.innerText = this.$versionFound.innerText.replace('#VERSION#', this.result);
|
||||
this.$versionFound.classList.remove('d-none');
|
||||
} else if (this.result === true) {
|
||||
this.$success.classList.remove('d-none');
|
||||
} else {
|
||||
this.$failed.classList.remove('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
async checkForUpdate () {
|
||||
return fetch(window.appData.routes.fetch.updateCheck, {
|
||||
credentials: 'same-origin',
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
}).then((response) => {
|
||||
return response.json();
|
||||
}).then((results) => {
|
||||
return results.checkResult;
|
||||
}).catch(() => {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
@ -65,4 +65,10 @@ return [
|
||||
'cron_token_generate_failure' => 'A new cron token could not be generated. Please check your browser console and application logs for more information.',
|
||||
'cron_token_auth_failure' => 'The provided cron token is invalid',
|
||||
'cron_execute_successful' => 'Cron successfully executed',
|
||||
|
||||
'update_check' => 'Update Check',
|
||||
'update_check_running' => 'Checking for updates...',
|
||||
'update_check_version_found' => 'Update found. Version #VERSION# is available.',
|
||||
'update_check_success' => 'No update found.',
|
||||
'update_check_failed' => 'Could not check for updates.',
|
||||
];
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="card">
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
@lang('settings.cron_token')
|
||||
</div>
|
||||
|
@ -0,0 +1,13 @@
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
@lang('settings.update_check')
|
||||
</div>
|
||||
<div class="update-check card-body small">
|
||||
|
||||
<div class="update-check-running">@lang('settings.update_check_running')</div>
|
||||
<div class="update-check-version-found text-success d-none">@lang('settings.update_check_version_found')</div>
|
||||
<div class="update-check-success d-none">@lang('settings.update_check_success')</div>
|
||||
<div class="update-check-failed text-danger d-none">@lang('settings.update_check_failed')</div>
|
||||
|
||||
</div>
|
||||
</div>
|
@ -2,6 +2,8 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
@include('actions.settings.partials.system.updates')
|
||||
|
||||
@include('actions.settings.partials.system.cron')
|
||||
|
||||
@include('actions.settings.partials.system.general-settings')
|
||||
|
@ -31,6 +31,7 @@
|
||||
'searchLists' => route('fetch-lists'),
|
||||
'searchTags' => route('fetch-tags'),
|
||||
'existingLinks' => route('fetch-existing-links'),
|
||||
'updateCheck' => route('fetch-update-check'),
|
||||
'generateApiToken' => route('generate-api-token'),
|
||||
'generateCronToken' => route('generate-cron-token'),
|
||||
]
|
||||
|
@ -136,6 +136,8 @@ Route::group(['middleware' => ['auth']], function () {
|
||||
->name('fetch-lists');
|
||||
Route::post('fetch/existing-links', [FetchController::class, 'searchExistingUrls'])
|
||||
->name('fetch-existing-links');
|
||||
Route::get('fetch/update-check', [FetchController::class, 'checkForUpdates'])
|
||||
->name('fetch-update-check');
|
||||
});
|
||||
|
||||
// Guest access routes
|
||||
|
Loading…
x
Reference in New Issue
Block a user