diff --git a/README.md b/README.md index 3e0db2f..4c6bdaa 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,14 @@ Copy the config.sample.json file and rename to config.json. Be sure to update th - `idle_timer` => Set a number of milliseconds here if you'd like to automatically hide the menu after a certain time of inactivity. Leave this attribute out entirely if you don't want an idle timer. - `show_menu_on_page_load` => Boolean whether to show the menu on page load, otherwise hide it. Defaults to false, i.e. hidden. - `open_links_in_new_tab` => Boolean whether to open all links in a new tab. Defaults to false, i.e. open links in current tab. -- `cloudron_api_url` => The url of your Cloudron dashboard, i.e. `https://my.example.com`. +- `cloudron_api_url` => The url of your Cloudron dashboard, i.e. `https://my.example.com`. This will be automatically filled out upon Cloudron installation. +- `custom_links` => An optional array of objects for custom links to add to the dashboard. Objects can accept the following attributes: + - `url` => `https://` or `http://` prefixed URL of site + - `title` => Title of page, i.e. Apple, or Nextcloud + - `image` => URL of image. Can be remote or local file. Provide either `image` or `icon`. + - `icon` => [Font Awesome icon name](https://fontawesome.com/icons). Provide either `image` or `icon`. + - `ordinal` => Ordinal integer for where you want the icon to show up in the dashboard +- `cloudron_app_ordinals` => An optional object to provide ordinal values for your Cloudron apps. The key should be your Cloudron app GUID, i.e. a 36 character string. The value should be the ordinal integer you want for this link. If not supplied, each Cloudron app will automatically get assigned an ordinal of `100 * index` in the order they come back from the API call, e.g. the first app returned will have an ordinal of 0, the second app will have an ordinal of 100, etc. - `cloudron_api_access_token` => An API access token so that we can query the apps installed in the Cloudron instance. You can get an API access token by visiting your Cloudron dashboard and adding an `/profile` to the end of the url instead of `/apps`, i.e. `https://my.example.com/#/profile`. __NOTE__: PHP cURL is required for fetching external images. diff --git a/src/config.sample.json b/src/config.sample.json index c20d857..43ff6cd 100644 --- a/src/config.sample.json +++ b/src/config.sample.json @@ -8,6 +8,17 @@ "show_menu_on_page_load": false, "open_links_in_new_tab": false, "cloudron_api_url": "", + "custom_links": [ + { + "url": "example.com", + "title": "Example", + "icon": "star", + "ordinal": 1 + } + ], + "cloudron_app_ordinals": { + "app-guid": 123 + }, "protected": { "cloudron_api_access_token": "", "custom_url" : "", diff --git a/src/hp_assets/js/main.js b/src/hp_assets/js/main.js index 1e790ba..ef092ef 100644 --- a/src/hp_assets/js/main.js +++ b/src/hp_assets/js/main.js @@ -113,31 +113,47 @@ function updateClock () { document.getElementById("clock").textContent = new Date().format($.config.clock_format); } +// Ensure that any URL has an 'http://' or 'https://' prepended +function httpize(url) { + return (url.indexOf("://") === -1) ? `http://${url}` : url; +} + // Do async request to get Cloudron apps function getCloudronApps() { $.getJSON("hp_assets/lib/ajax_get_apps.php").done(function(data) { if (data['success']) { $.config.apps = data['apps'] || []; - // Trigger the rendering of the apps - renderCloudronApps(); + // Create a single array that is the combination of our Cloudron apps and additional links + $.config.all_links = [].concat($.config.apps, $.config.custom_links || []); + + // Sort our super array by ordinal + $.config.all_links.sort((a, b) => a.ordinal > b.ordinal); + + // Trigger the rendering of all of our links + renderLinks(); } }); } // Once we have populated our apps in the config variable, render them properly -function renderCloudronApps() { +function renderLinks() { const wrapperEl = document.getElementById("links-wrap"); - $.config.apps.map((app) => { + $.config.all_links.map((app) => { const appName = app.title; const newTabStr = $.config.open_links_in_new_tab ? " target=\"_blank\" rel=\"noopener noreferrer\"" : ""; - const appDiv = ``; + const iconOrImage = app.image ? + `${appName}` + : + ``; + + const appDiv = ``; wrapperEl.innerHTML += appDiv; }); // Set key bindings for the first 9 apps - let appsLengthOrNine = $.config.apps.length >= 9 ? 9 : $.config.apps.length; + let appsLengthOrNine = $.config.all_links.length >= 9 ? 9 : $.config.all_links.length; for (let i = 0; i < appsLengthOrNine; i++) { let oneBasedIndex = i + 1; Mousetrap.bind(`${oneBasedIndex}`, function() { diff --git a/src/hp_assets/lib/ajax_get_apps.php b/src/hp_assets/lib/ajax_get_apps.php index f1428d5..2cf8095 100644 --- a/src/hp_assets/lib/ajax_get_apps.php +++ b/src/hp_assets/lib/ajax_get_apps.php @@ -12,13 +12,18 @@ $json = json_decode(curl_get_contents($url), true); // Let's clean up our 'apps' response object to only send back pertinent information - $apps = array_map(function($app) { - return array( - 'id' => $app['id'], - 'fqdn' => $app['fqdn'], - 'title' => $app['manifest']['title'] + $apps = $json['apps']; + foreach ($apps as $key => &$app) { + $app_id = $app['id']; + $app = array( + 'id' => $app_id, + 'url' => "https://{$app['fqdn']}", + 'title' => $app['manifest']['title'], + 'image' => "hp_assets/lib/render_cloudron_app_icon.php?cloudron_app_id={$app_id}", + // Ordinal will either be pulled from config file if set, otherwise it'll be 100 times its index in the array + 'ordinal' => $config['cloudron_app_ordinals'][$app_id] ? $config['cloudron_app_ordinals'][$app_id] : $key * 100 ); - }, $json['apps']); + } echo json_encode(array('success' => 1, 'apps' => $apps)); }