Sergio Brighenti 5 years ago
parent
commit
8e85f251b8

+ 3 - 1
CHANGELOG.md

@@ -1,5 +1,7 @@
 ## v.3.1 (WIP)
 ## v.3.1 (WIP)
-+ Updated translations
++ Updated system settings page.
++ Added hide by default option.
++ Updated translations.
 
 
 ## v.3.0.2
 ## v.3.0.2
 + Fixed error with migrate command.
 + Fixed error with migrate command.

+ 30 - 45
app/Controllers/AdminController.php

@@ -9,15 +9,15 @@ use Psr\Http\Message\ServerRequestInterface as Request;
 class AdminController extends Controller
 class AdminController extends Controller
 {
 {
     /**
     /**
-     * @param Request  $request
-     * @param Response $response
+     * @param  Request  $request
+     * @param  Response  $response
      *
      *
-     * @throws FileNotFoundException
+     * @return Response
      * @throws \Twig\Error\LoaderError
      * @throws \Twig\Error\LoaderError
      * @throws \Twig\Error\RuntimeError
      * @throws \Twig\Error\RuntimeError
      * @throws \Twig\Error\SyntaxError
      * @throws \Twig\Error\SyntaxError
      *
      *
-     * @return Response
+     * @throws FileNotFoundException
      */
      */
     public function system(Request $request, Response $response): Response
     public function system(Request $request, Response $response): Response
     {
     {
@@ -34,22 +34,30 @@ class AdminController extends Controller
             $totalSize += $filesystem->getSize($media->storage_path);
             $totalSize += $filesystem->getSize($media->storage_path);
         }
         }
 
 
+        $registerEnabled = $this->database->query('SELECT `value` FROM `settings` WHERE `key` = \'register_enabled\'')->fetch()->value;
+        $hideByDefault = $this->database->query('SELECT `value` FROM `settings` WHERE `key` = \'hide_by_default\'')->fetch()->value;
+        $copyUrl = $this->database->query('SELECT `value` FROM `settings` WHERE `key` = \'copy_url_behavior\'')->fetch()->value;
+
         return view()->render($response, 'dashboard/system.twig', [
         return view()->render($response, 'dashboard/system.twig', [
-            'usersCount'          => $usersCount,
-            'mediasCount'         => $mediasCount,
-            'orphanFilesCount'    => $orphanFilesCount,
-            'totalSize'           => humanFileSize($totalSize),
-            'post_max_size'       => ini_get('post_max_size'),
+            'usersCount' => $usersCount,
+            'mediasCount' => $mediasCount,
+            'orphanFilesCount' => $orphanFilesCount,
+            'totalSize' => humanFileSize($totalSize),
+            'post_max_size' => ini_get('post_max_size'),
             'upload_max_filesize' => ini_get('upload_max_filesize'),
             'upload_max_filesize' => ini_get('upload_max_filesize'),
-            'installed_lang'      => $this->lang->getList(),
-            'forced_lang'         => $request->getAttribute('forced_lang'),
-            'php_version'         => phpversion(),
+            'installed_lang' => $this->lang->getList(),
+            'forced_lang' => $request->getAttribute('forced_lang'),
+            'php_version' => phpversion(),
+            'max_memory' => ini_get('memory_limit'),
+            'register_enabled' => $registerEnabled,
+            'hide_by_default' => $hideByDefault,
+            'copy_url_behavior' => $copyUrl,
         ]);
         ]);
     }
     }
 
 
     /**
     /**
-     * @param Request  $request
-     * @param Response $response
+     * @param  Request  $request
+     * @param  Response  $response
      *
      *
      * @return Response
      * @return Response
      */
      */
@@ -76,44 +84,21 @@ class AdminController extends Controller
     }
     }
 
 
     /**
     /**
-     * @param Request  $request
-     * @param Response $response
+     * @param  Response  $response
      *
      *
      * @return Response
      * @return Response
      */
      */
-    public function applyLang(Request $request, Response $response): Response
+    public function getThemes(Response $response): Response
     {
     {
-        if (param($request, 'lang') !== 'auto') {
-            if (!$this->database->query('SELECT `value` FROM `settings` WHERE `key` = \'lang\'')->fetch()) {
-                $this->database->query('INSERT INTO `settings`(`key`, `value`) VALUES (\'lang\', ?)', param($request, 'lang'));
-            } else {
-                $this->database->query('UPDATE `settings` SET `value`=? WHERE `key` = \'lang\'', param($request, 'lang'));
-            }
-        } else {
-            $this->database->query('DELETE FROM `settings` WHERE `key` = \'lang\'');
-        }
+        $apiJson = json_decode(file_get_contents('https://bootswatch.com/api/4.json'));
 
 
-        $this->session->alert(lang('lang_set', [param($request, 'lang')]));
+        $out = [];
 
 
-        return redirect($response, route('system'));
-    }
-
-    /**
-     * @param Request  $request
-     * @param Response $response
-     *
-     * @return Response
-     */
-    public function applyCustomHead(Request $request, Response $response): Response
-    {
-        if ($request->getAttribute('custom_head_key_present')) {
-            $this->database->query('UPDATE `settings` SET `value`=? WHERE `key` = \'custom_head\'', param($request, 'custom_head'));
-        } else {
-            $this->database->query('INSERT INTO `settings`(`key`, `value`) VALUES (\'custom_head\', ?)', param($request, 'custom_head'));
+        $out['Default - Bootstrap 4 default theme'] = 'https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css';
+        foreach ($apiJson->themes as $theme) {
+            $out["{$theme->name} - {$theme->description}"] = $theme->cssMin;
         }
         }
 
 
-        $this->session->alert(lang('custom_head_set'));
-
-        return redirect($response, route('system'));
+        return json($response, $out);
     }
     }
 }
 }

+ 81 - 0
app/Controllers/SettingController.php

@@ -4,7 +4,88 @@
 namespace App\Controllers;
 namespace App\Controllers;
 
 
 
 
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+
 class SettingController extends Controller
 class SettingController extends Controller
 {
 {
+    /**
+     * @param  Request  $request
+     * @param  Response  $response
+     *
+     * @return Response
+     */
+    public function saveSettings(Request $request, Response $response): Response
+    {
+        $this->settingUpdate('register_enabled', param($request, 'register_enabled', 'off'));
+        $this->settingUpdate('hide_by_default', param($request, 'hide_by_default', 'off'));
+        $this->settingUpdate('copy_url_behavior', param($request, 'copy_url_behavior', 'off'));
+
+        $this->applyTheme($request);
+        $this->applyLang($request);
+        $this->saveCustomHead($request);
+
+        $this->session->alert(lang('settings_saved'));
+
+        return redirect($response, route('system'));
+    }
+
+    /**
+     * @param  Request  $request
+     */
+    public function applyLang(Request $request)
+    {
+        if (param($request, 'lang') !== 'auto') {
+            if (!$this->database->query('SELECT `value` FROM `settings` WHERE `key` = \'lang\'')->fetch()) {
+                $this->database->query('INSERT INTO `settings`(`key`, `value`) VALUES (\'lang\', ?)', param($request, 'lang'));
+            } else {
+                $this->database->query('UPDATE `settings` SET `value`=? WHERE `key` = \'lang\'', param($request, 'lang'));
+            }
+        } else {
+            $this->database->query('DELETE FROM `settings` WHERE `key` = \'lang\'');
+        }
+    }
+
+    /**
+     * @param  Request  $request
+     */
+    public function saveCustomHead(Request $request)
+    {
+        if ($request->getAttribute('custom_head_key_present')) {
+            $this->database->query('UPDATE `settings` SET `value`=? WHERE `key` = \'custom_head\'', param($request, 'custom_head'));
+        } else {
+            $this->database->query('INSERT INTO `settings`(`key`, `value`) VALUES (\'custom_head\', ?)', param($request, 'custom_head'));
+        }
+    }
+
+
+    /**
+     * @param  Request  $request
+     */
+    public function applyTheme(Request $request)
+    {
+        if (param($request, 'css') !== null) {
+            if (!is_writable(BASE_DIR.'static/bootstrap/css/bootstrap.min.css')) {
+                $this->session->alert(lang('cannot_write_file'), 'danger');
+
+            } else {
+                file_put_contents(BASE_DIR.'static/bootstrap/css/bootstrap.min.css', file_get_contents(param($request, 'css')));
+            }
+
+            $this->settingUpdate('css', param($request, 'css'));
+        }
+    }
 
 
+    /**
+     * @param $key
+     * @param  null  $value
+     */
+    private function settingUpdate($key, $value = null)
+    {
+        if (!$this->database->query('SELECT `value` FROM `settings` WHERE `key` = '.$this->database->getPdo()->quote($key))->fetch()) {
+            $this->database->query('INSERT INTO `settings`(`key`, `value`) VALUES ('.$this->database->getPdo()->quote($key).', ?)', $value);
+        } else {
+            $this->database->query('UPDATE `settings` SET `value`=? WHERE `key` = '.$this->database->getPdo()->quote($key), $value);
+        }
+    }
 }
 }

+ 0 - 47
app/Controllers/ThemeController.php

@@ -1,47 +0,0 @@
-<?php
-
-namespace App\Controllers;
-
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-
-class ThemeController extends Controller
-{
-    /**
-     * @param Response $response
-     *
-     * @return Response
-     */
-    public function getThemes(Response $response): Response
-    {
-        $apiJson = json_decode(file_get_contents('https://bootswatch.com/api/4.json'));
-
-        $out = [];
-
-        $out['Default - Bootstrap 4 default theme'] = 'https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css';
-        foreach ($apiJson->themes as $theme) {
-            $out["{$theme->name} - {$theme->description}"] = $theme->cssMin;
-        }
-
-        return json($response, $out);
-    }
-
-    /**
-     * @param Request  $request
-     * @param Response $response
-     *
-     * @return Response
-     */
-    public function applyTheme(Request $request, Response $response): Response
-    {
-        if (!is_writable(BASE_DIR.'static/bootstrap/css/bootstrap.min.css')) {
-            $this->session->alert(lang('cannot_write_file'), 'danger');
-
-            return redirect($response, route('system'));
-        }
-
-        file_put_contents(BASE_DIR.'static/bootstrap/css/bootstrap.min.css', file_get_contents(param($request, 'css')));
-
-        return redirect($response, route('system'));
-    }
-}

+ 7 - 1
app/Controllers/UploadController.php

@@ -100,16 +100,22 @@ class UploadController extends Controller
             $code = humanRandomString();
             $code = humanRandomString();
         } while ($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `code` = ?', $code)->fetch()->count > 0);
         } while ($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `code` = ?', $code)->fetch()->count > 0);
 
 
+        $published = 1;
+        if ($this->database->query('SELECT `value` FROM `settings` WHERE `key` = \'hide_by_default\'')->fetch()->value === 'on') {
+            $published = 0;
+        }
+
         $fileInfo = pathinfo($file->getClientFilename());
         $fileInfo = pathinfo($file->getClientFilename());
         $storagePath = "$user->user_code/$code.$fileInfo[extension]";
         $storagePath = "$user->user_code/$code.$fileInfo[extension]";
 
 
         $this->storage->writeStream($storagePath, $file->getStream()->detach());
         $this->storage->writeStream($storagePath, $file->getStream()->detach());
 
 
-        $this->database->query('INSERT INTO `uploads`(`user_id`, `code`, `filename`, `storage_path`) VALUES (?, ?, ?, ?)', [
+        $this->database->query('INSERT INTO `uploads`(`user_id`, `code`, `filename`, `storage_path`, `published`) VALUES (?, ?, ?, ?, ?)', [
             $user->id,
             $user->id,
             $code,
             $code,
             $file->getClientFilename(),
             $file->getClientFilename(),
             $storagePath,
             $storagePath,
+            $published,
         ]);
         ]);
 
 
         $json['message'] = 'OK.';
         $json['message'] = 'OK.';

+ 3 - 5
app/routes.php

@@ -6,6 +6,7 @@ use App\Controllers\ClientController;
 use App\Controllers\DashboardController;
 use App\Controllers\DashboardController;
 use App\Controllers\LoginController;
 use App\Controllers\LoginController;
 use App\Controllers\MediaController;
 use App\Controllers\MediaController;
+use App\Controllers\SettingController;
 use App\Controllers\ThemeController;
 use App\Controllers\ThemeController;
 use App\Controllers\UpgradeController;
 use App\Controllers\UpgradeController;
 use App\Controllers\UploadController;
 use App\Controllers\UploadController;
@@ -25,12 +26,9 @@ $app->group('', function (RouteCollectorProxy $group) {
 
 
         $group->get('/system/deleteOrphanFiles', [AdminController::class, 'deleteOrphanFiles'])->setName('system.deleteOrphanFiles');
         $group->get('/system/deleteOrphanFiles', [AdminController::class, 'deleteOrphanFiles'])->setName('system.deleteOrphanFiles');
 
 
-        $group->get('/system/themes', [ThemeController::class, 'getThemes'])->setName('theme');
-        $group->post('/system/theme/apply', [ThemeController::class, 'applyTheme'])->setName('theme.apply');
+        $group->get('/system/themes', [AdminController::class, 'getThemes'])->setName('theme');
 
 
-        $group->post('/system/lang/apply', [AdminController::class, 'applyLang'])->setName('lang.apply');
-
-        $group->post('/system/customHead', [AdminController::class, 'applyCustomHead'])->setName('customHead.apply');
+        $group->post('/system/settings/save', [SettingController::class, 'saveSettings'])->setName('settings.save');
 
 
         $group->post('/system/upgrade', [UpgradeController::class, 'upgrade'])->setName('system.upgrade');
         $group->post('/system/upgrade', [UpgradeController::class, 'upgrade'])->setName('system.upgrade');
         $group->get('/system/checkForUpdates', [UpgradeController::class, 'checkForUpdates'])->setName('system.checkForUpdates');
         $group->get('/system/checkForUpdates', [UpgradeController::class, 'checkForUpdates'])->setName('system.checkForUpdates');

+ 4 - 1
resources/lang/en.lang.php

@@ -100,7 +100,6 @@ return [
     'cancel'                  => 'Cancel',
     'cancel'                  => 'Cancel',
     'auto_set'                => 'Set automatically',
     'auto_set'                => 'Set automatically',
     'default_lang_behavior'   => 'XBackBone will try to match the browser language by default (the fallback is English).',
     'default_lang_behavior'   => 'XBackBone will try to match the browser language by default (the fallback is English).',
-    'lang_set'                => 'System language enforced to "%s"',
     'prerelease_channel'      => 'Prerelease Channel',
     'prerelease_channel'      => 'Prerelease Channel',
     'no_upload_token'         => 'You don\'t have a personal upload token. (Generate one and try again.)',
     'no_upload_token'         => 'You don\'t have a personal upload token. (Generate one and try again.)',
     'drop_to_upload'          => 'Click or drop your files here to upload.',
     'drop_to_upload'          => 'Click or drop your files here to upload.',
@@ -112,4 +111,8 @@ return [
     'remember_me'             => 'Remember me',
     'remember_me'             => 'Remember me',
     'please_wait'             => 'Please wait…',
     'please_wait'             => 'Please wait…',
     'dont_close'              => 'Do not close this tab until completion.',
     'dont_close'              => 'Do not close this tab until completion.',
+    'register_enabled'              => 'Registration Enabled',
+    'hide_by_default'              => 'Hide uploads by default',
+    'copy_url_behavior'              => 'Copy URL mode',
+    'settings_saved'              => 'System settings saved!',
 ];
 ];

+ 5 - 74
resources/templates/dashboard/system.twig

@@ -58,32 +58,29 @@
                 <div class="card shadow-sm mt-3">
                 <div class="card shadow-sm mt-3">
                     <div class="card-header"><i class="fas fa-cog fa-fw"></i> {{ lang('system_settings') }}</div>
                     <div class="card-header"><i class="fas fa-cog fa-fw"></i> {{ lang('system_settings') }}</div>
                     <div class="card-body">
                     <div class="card-body">
-                        <form method="post" action="{#{{ route('systemSettings.apply') }}#}">
-
-
+                        <form method="post" action="{{ route('settings.save') }}">
 
 
                             <div class="form-group row">
                             <div class="form-group row">
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('register_enabled') }}</label>
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('register_enabled') }}</label>
                                 <div class="col-sm-8">
                                 <div class="col-sm-8">
-                                    <input type="checkbox" checked data-toggle="toggle">
+                                    <input type="checkbox" name="register_enabled" data-toggle="toggle" {{ register_enabled == 'on' ? 'checked' }}>
                                 </div>
                                 </div>
                             </div>
                             </div>
 
 
                             <div class="form-group row">
                             <div class="form-group row">
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('hide_by_default') }}</label>
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('hide_by_default') }}</label>
                                 <div class="col-sm-8">
                                 <div class="col-sm-8">
-                                    <input type="checkbox" checked data-toggle="toggle">
+                                    <input type="checkbox" name="hide_by_default" data-toggle="toggle" {{ hide_by_default == 'on' ? 'checked' }}>
                                 </div>
                                 </div>
                             </div>
                             </div>
 
 
                             <div class="form-group row">
                             <div class="form-group row">
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('copy_url_behavior') }}</label>
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('copy_url_behavior') }}</label>
                                 <div class="col-sm-8">
                                 <div class="col-sm-8">
-                                    <input type="checkbox" checked data-toggle="toggle" data-on="Default URL" data-off="Raw URL" data-onstyle="primary" data-offstyle="secondary">
+                                    <input type="checkbox" name="copy_url_behavior" data-toggle="toggle" data-off="Default URL" data-on="Raw URL" data-onstyle="primary" data-offstyle="secondary" {{ copy_url_behavior == 'on' ? 'checked' }}>
                                 </div>
                                 </div>
                             </div>
                             </div>
 
 
-
                             <div class="form-group row">
                             <div class="form-group row">
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('theme') }}</label>
                                 <label for="custom_head" class="col-sm-4 col-form-label">{{ lang('theme') }}</label>
                                 <div class="col-sm-8">
                                 <div class="col-sm-8">
@@ -120,61 +117,6 @@
                         </form>
                         </form>
                     </div>
                     </div>
                 </div>
                 </div>
-
-
-
-                {#<div class="row same-height-container">
-                    <div class="col-md-6 mt-3">
-                        <div class="card shadow-sm same-height">
-                            <div class="card-header"><i class="fas fa-paint-brush fa-fw"></i> {{ lang('theme') }}</div>
-                            <div class="card-body">
-                                <form method="post" action="{{ route('theme.apply') }}">
-                                    <div class="form-group row">
-                                        <div class="col-sm-12">
-                                            <select class="form-control" id="themes" name="css">
-                                                <option id="theme-load" selected disabled hidden>{{ lang('click_to_load') }}</option>
-                                            </select>
-                                        </div>
-                                    </div>
-                                    <div class="form-group row">
-                                        <div class="col-sm-12">
-                                            <button type="submit" class="btn btn-outline-success float-right" id="themes-apply" disabled>
-                                                <i class="fas fa-save fa-fw"></i> {{ lang('apply') }}
-                                            </button>
-                                        </div>
-                                    </div>
-                                </form>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="col-md-6 mt-3">
-                        <div class="card shadow-sm same-height">
-                            <div class="card-header"><i class="fas fa-language fa-fw"></i> {{ lang('enforce_language') }}</div>
-                            <div class="card-body">
-                                <form method="post" action="{{ route('lang.apply') }}">
-                                    <div class="form-group row">
-                                        <div class="col-sm-12">
-                                            <select class="form-control" id="lang" name="lang">
-                                                <option value="auto">({{ lang('auto_set') }})</option>
-                                                {% for lang, name in installed_lang %}
-                                                    <option value="{{ lang }}"{{ forced_lang == lang ? ' selected' }}>{{ name }}</option>
-                                                {% endfor %}
-                                            </select>
-                                            <small>{{ lang('default_lang_behavior') }}</small>
-                                        </div>
-                                    </div>
-                                    <div class="form-group row">
-                                        <div class="col-sm-12">
-                                            <button type="submit" class="btn btn-outline-success float-right" id="lang-apply">
-                                                <i class="fas fa-save fa-fw"></i> {{ lang('apply') }}
-                                            </button>
-                                        </div>
-                                    </div>
-                                </form>
-                            </div>
-                        </div>
-                    </div>
-                </div>#}
                 <div class="card shadow-sm mt-3">
                 <div class="card shadow-sm mt-3">
                     <div class="card-header"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('updates') }} <span class="float-right">v{{ PLATFORM_VERSION }}</span></div>
                     <div class="card-header"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('updates') }} <span class="float-right">v{{ PLATFORM_VERSION }}</span></div>
                     <div class="card-body">
                     <div class="card-body">
@@ -200,24 +142,13 @@
                         </div>
                         </div>
                     </div>
                     </div>
                 </div>
                 </div>
-{#                <div class="card shadow-sm mt-3">#}
-{#                    <div class="card-header"><i class="fas fa-code fa-fw"></i> {{ lang('custom_head_html') }}</div>#}
-{#                    <div class="card-body">#}
-{#                        <form method="post" action="{{ route('customHead.apply') }}">#}
-{#                            <textarea name="custom_head" class="form-control text-monospace">{{ customHead|raw }}</textarea>#}
-{#                            <small>{{ lang('custom_head_html_hint') }}</small>#}
-{#                            <button type="submit" class="btn btn-outline-success float-right mt-3">#}
-{#                                <i class="fas fa-save fa-fw"></i> {{ lang('apply') }}#}
-{#                            </button>#}
-{#                        </form>#}
-{#                    </div>#}
-{#                </div>#}
             </div>
             </div>
             <div class="col-md-4 mt-3">
             <div class="col-md-4 mt-3">
                 <div class="card shadow-sm">
                 <div class="card shadow-sm">
                     <div class="card-header"><i class="fab fa-php fa-fw"></i> {{ lang('php_info') }}</div>
                     <div class="card-header"><i class="fab fa-php fa-fw"></i> {{ lang('php_info') }}</div>
                     <div class="card-body">
                     <div class="card-body">
                         <strong>PHP Version:</strong> {{ php_version }}<br>
                         <strong>PHP Version:</strong> {{ php_version }}<br>
+                        <strong>Max memory usage:</strong> {{ max_memory }}<br>
                         <strong>Max upload size:</strong>
                         <strong>Max upload size:</strong>
                         <ul>
                         <ul>
                             <li><code>post_max_size</code>: {{ post_max_size }}</li>
                             <li><code>post_max_size</code>: {{ post_max_size }}</li>

+ 1 - 12
src/js/app.js

@@ -34,16 +34,6 @@ var app = {
 
 
         $('.footer').fadeIn(600);
         $('.footer').fadeIn(600);
 
 
-        $('.same-height-container').each(function () {
-            var highestBox = 0;
-            $('.same-height', this).each(function () {
-                if ($(this).height() > highestBox) {
-                    highestBox = $(this).height();
-                }
-            });
-            $('.same-height', this).height(highestBox);
-        });
-
         console.log('Application is ready.');
         console.log('Application is ready.');
     },
     },
     modalDelete: function () {
     modalDelete: function () {
@@ -109,7 +99,6 @@ var app = {
                 opt.innerHTML = key;
                 opt.innerHTML = key;
                 $themes.append(opt);
                 $themes.append(opt);
             });
             });
-            $('#themes-apply').prop('disabled', false);
         });
         });
         $themes.unbind('mousedown');
         $themes.unbind('mousedown');
     },
     },
@@ -117,7 +106,7 @@ var app = {
         window.open($('#telegram-share-button').data('url') + $('#telegram-share-text').val(), '_blank');
         window.open($('#telegram-share-button').data('url') + $('#telegram-share-text').val(), '_blank');
     },
     },
     checkForUpdates: function () {
     checkForUpdates: function () {
-        $('#checkForUpdatesMessage').empty().text('...');
+        $('#checkForUpdatesMessage').empty().html('<i class="fas fa-sync fa-spin"></i>');
         $('#doUpgradeButton').prop('disabled', true);
         $('#doUpgradeButton').prop('disabled', true);
         $.get(window.AppConfig.base_url + '/system/checkForUpdates?prerelease=' + $(this).data('prerelease'), function (data) {
         $.get(window.AppConfig.base_url + '/system/checkForUpdates?prerelease=' + $(this).data('prerelease'), function (data) {
             $('#checkForUpdatesMessage').empty().text(data.message);
             $('#checkForUpdatesMessage').empty().text(data.message);