devshort

private self-hosted shortlink service
git clone https://git.clttr.info/devshort.git
Log (Feed) | Files | Refs (Tags) | README | LICENSE

commit 31bcbe31d94b3a6651b37d1f6094c2f95bbe58a9
parent 935022e3dcdbdcc5a7ec70738447dec5b38b4bce
Author: Florian <flokX@users.noreply.github.com>
Date:   Sat,  2 Feb 2019 11:52:23 +0100

Merge pull request #3 from flokX/flokX-patch-1

Admin panel improvements
Diffstat:
Madmin/index.php | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Madmin/main.js | 68+++++++++++++++++++++++++++++++++++++++++++++++---------------------
Madmin/stats.json | 4+++-
Dassets/main.min.css | 1-
Minstaller.php | 2+-
Mredirect.php | 2+-
6 files changed, 119 insertions(+), 50 deletions(-)

diff --git a/admin/index.php b/admin/index.php @@ -2,31 +2,54 @@ // All relevant changes can be made in the data file. Please read the docs: https://github.com/flokX/devShort/wiki -$name = htmlspecialchars($_POST["delete"]); - -$base_path = __DIR__; -$data = json_decode(file_get_contents($base_path . DIRECTORY_SEPARATOR . "config.json"), true); - -if (isset($_POST["delete"])) { - $filename = $base_path . DIRECTORY_SEPARATOR . "config.json"; - $content = json_decode(file_get_contents($filename), true); - unset($content["shortlinks"][$name]); - file_put_contents($filename, json_encode($content, JSON_PRETTY_PRINT)); - - $filename = $base_path . DIRECTORY_SEPARATOR . "stats.json"; - $content = json_decode(file_get_contents($filename), true); - unset($content[$name]); - file_put_contents($filename, json_encode($content, JSON_PRETTY_PRINT)); +$config_filename = __DIR__ . DIRECTORY_SEPARATOR . "config.json"; +$config_content = json_decode(file_get_contents($config_filename), true); +$stats_filename = __DIR__ . DIRECTORY_SEPARATOR . "stats.json"; +$stats_content = json_decode(file_get_contents($stats_filename), true); + +// API functions to delte and add the shortlinks via the admin panel +if (isset($_GET["delete"]) || isset($_GET["add"])) { + $name = htmlspecialchars($_POST["name"]); + $link = htmlspecialchars($_POST["link"]); + + if (isset($_GET["delete"])) { + unset($config_content["shortlinks"][$name]); + unset($stats_content[$name]); + } else if (isset($_GET["add"])) { + $config_content["shortlinks"][$name] = $link; + $stats_content[$name] = array(); + } + file_put_contents($config_filename, json_encode($config_content, JSON_PRETTY_PRINT)); + file_put_contents($stats_filename, json_encode($stats_content, JSON_PRETTY_PRINT)); echo "{\"status\": \"successful\"}"; exit; } +// Check if there are links which are only in the config.json or only in the stats.json +$changed = false; +foreach ($config_content["shortlinks"] as $name => $url) { + if (!isset($stats_content[$name])) { + $stats_content[$name] = array(); + $changed = true; + } +} +foreach ($stats_content as $name => $stats) { + if (!isset($config_content["shortlinks"][$name]) && $name !== "404-request") { + unset($stats_content[$name]); + $changed = true; + } +} +if ($changed) { + file_put_contents($config_filename, json_encode($config_content, JSON_PRETTY_PRINT)); + file_put_contents($stats_filename, json_encode($stats_content, JSON_PRETTY_PRINT)); +} + // Generator for page customization $links_string = ""; -if ($data["settings"]["custom_links"]) { - foreach ($data["settings"]["custom_links"] as $name => $url) { - $links_string = $links_string . "<a href=\"$url\" class=\"badgebadge-secondary\">$name</a> "; +if ($config_content["settings"]["custom_links"]) { + foreach ($config_content["settings"]["custom_links"] as $name => $url) { + $links_string = $links_string . "<a href=\"$url\" class=\"badge badge-secondary\">$name</a> "; } $links_string = substr($links_string, 0, -1); } @@ -40,27 +63,46 @@ if ($data["settings"]["custom_links"]) { <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="robots" content="noindex, nofollow"> - <meta name="author" content="<?php echo $data["settings"]["author"]; ?> and the devShort team"> - <link rel="icon" href="../<?php echo $data["settings"]["favicon"]; ?>"> - <title>Admin console | <?php echo $data["settings"]["name"]; ?></title> + <meta name="author" content="<?php echo $config_content[" settings"]["author"]; ?> and the devShort team"> + <link rel="icon" href="../<?php echo $config_content[" settings"]["favicon"]; ?>"> + <title>Admin panel | <?php echo $config_content["settings"]["name"]; ?></title> <link href="../assets/vendor/bootstrap/bootstrap.min.css" rel="stylesheet"> - <link href="../assets/main.min.css" rel="stylesheet"> + <link href="../assets/main.css" rel="stylesheet"> </head> <body class="d-flex flex-column h-100"> <main role="main" class="flex-shrink-0"> <div class="container"> - <h1 class="mt-5 mb-4 text-center"><?php echo $data["settings"]["name"]; ?> admin console</h1> + <h1 class="mt-5 text-center"><?php echo $config_content["settings"]["name"]; ?> + </h1> + <h4 class="mb-4 text-center">admin panel</h4> + <div class="card mb-3"> + <div class="card-body"> + <h5 class="card-title">Add shortlink <a id="refresh" href="#refresh" class="card-link">Refresh charts</a></h5> + <form class="form-inline"> + <label class="sr-only" for="name">Name</label> + <input type="text" class="form-control mb-2 mr-sm-2" id="name" placeholder="Link1" aria-describedby="name-help"> + <label class="sr-only" for="link">Link (destination)</label> + <input type="text" class="form-control mb-2 mr-sm-2" id="link" placeholder="https://example.com"> + <button type="submit" id="add-shortlink" class="btn btn-primary mb-2">Add</button> + </form> + </div> + </div> + <div class="d-flex justify-content-center"> + <div id="spinner" class="spinner-border text-primary" role="status"> + <span class="sr-only">Loading...</span> + </div> + </div> <div id="charts"></div> - <p class="text-center mt-4">powered by <a href="https://github.com/flokX/devShort">devShort</a> v1.1.0 (Latest: <a href="https://github.com/flokX/devShort/releases"><img src="https://img.shields.io/github/release/flokX/devShort.svg?style=flat" alt="Latest release"></a>)</p> + <p class="text-center my-4">powered by <a href="https://github.com/flokX/devShort">devShort</a> v2.0.0 (Latest: <a href="https://github.com/flokX/devShort/releases"><img src="https://img.shields.io/github/release/flokX/devShort.svg?style=flat" alt="Latest release"></a>)</p> </div> </main> <footer class="footer mt-auto py-3"> <div class="container"> <div class="d-flex justify-content-between align-items-center"> - <span class="text-muted">&copy; <?php echo date("Y") . " " . $data["settings"]["author"]; ?> and <a href="https://github.com/flokX/devShort">devShort</a></span> + <span class="text-muted">&copy; <?php echo date("Y") . " " . $config_content["settings"]["author"]; ?> and <a href="https://github.com/flokX/devShort">devShort</a></span> <?php if ($links_string) { echo "<span class=\"text-muted\">$links_string</span>"; } ?> </div> </div> diff --git a/admin/main.js b/admin/main.js @@ -1,28 +1,54 @@ var currentDate = new Date(); var startDate = new Date(new Date().setFullYear(currentDate.getFullYear() - 1)); -$.getJSON('stats.json', function (json) { +$('button#add-shortlink').click(function (event) { + event.preventDefault(); + $('div#spinner').show(); + $.post('index.php?add', { + name: $('input#name').val(), + link: $('input#link').val() + }, function () { + $('input#name').val(''); + $('input#link').val(''); + getCharts(); + }); +}); +$('a#refresh').click(function (event) { + event.preventDefault(); + getCharts(); +}); + +function getCharts() { 'use strict'; - $.each(json, function (name, data) { - $('div#charts').append('<div class="card mb-3"><div class="card-body"><div id="heatmap-' + name + '" class="heatmap"></div></div><div class="card-footer text-center text-muted"><a id="export-' + name + '" href="#download" class="card-link">Download chart</a><a id="delete-' + name + '" href="#delete" class="card-link">Delete shortlink and dataset</a></div></div>'); - let heatmap = new frappe.Chart('div#heatmap-' + name, { - type: 'heatmap', - title: 'Access statistics for ' + name, - data: { - dataPoints: data, - start: startDate, - end: currentDate - }, - countLabel: 'Access(es)' - }); - $('a#export-' + name).click(function () { - heatmap.export(); - }); - $('a#delete-' + name).click(function () { - $.post('index.php', { - delete: name + $('div#spinner').show(); + $('div#charts').empty(); + $.getJSON('stats.json', function (json) { + $.each(json, function (name, data) { + $('div#charts').append('<div id="card-' + name + '" class="card mb-3"><div class="card-body"><div id="heatmap-' + name + '" class="heatmap"></div></div><div class="card-footer text-center text-muted"><a id="export-' + name + '" href="#download" class="card-link">Download chart</a><a id="delete-' + name + '" href="#delete" class="card-link">Delete shortlink and dataset</a></div></div>'); + let heatmap = new frappe.Chart('div#heatmap-' + name, { + type: 'heatmap', + title: 'Access statistics for ' + name, + data: { + dataPoints: data, + start: startDate, + end: currentDate + }, + countLabel: 'Access(es)' + }); + $('a#export-' + name).click(function (event) { + event.preventDefault(); + heatmap.export(); + }); + $('a#delete-' + name).click(function (event) { + event.preventDefault(); + $.post('index.php?delete', { + name: name + }); + $('div#card-' + name).remove(); }); - location.reload(); }); + $('div#spinner').hide(); }); -}); +} + +getCharts(); diff --git a/admin/stats.json b/admin/stats.json @@ -1 +1,3 @@ -{} +{ + "404-request": [] +} diff --git a/assets/main.min.css b/assets/main.min.css @@ -1 +0,0 @@ -.container{width:auto;max-width:680px;padding:0 15px}.footer{background-color:#f5f5f5}.heatmap{overflow-x:auto} diff --git a/installer.php b/installer.php @@ -60,7 +60,7 @@ require valid-user"; <link rel="icon" href="assets/icon.png"> <title>Installer | devShort</title> <link href="assets/vendor/bootstrap/bootstrap.min.css" rel="stylesheet"> - <link href="assets/main.min.css" rel="stylesheet"> + <link href="assets/main.css" rel="stylesheet"> </head> <body class="d-flex flex-column h-100"> diff --git a/redirect.php b/redirect.php @@ -57,7 +57,7 @@ if (array_key_exists($short, $data["shortlinks"])) { <link rel="icon" href="<?php echo $data["settings"]["favicon"]; ?>"> <title>404 | <?php echo $data["settings"]["name"]; ?></title> <link href="assets/vendor/bootstrap/bootstrap.min.css" rel="stylesheet"> - <link href="assets/main.min.css" rel="stylesheet"> + <link href="assets/main.css" rel="stylesheet"> </head> <body class="d-flex flex-column h-100">