devshort

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

commit 949f5ff9ab12d1eb8273737a16008fbff347c1eb
parent 50e585b5e80c6792717176402b974a5f3e1a890a
Author: Florian <flokX@users.noreply.github.com>
Date:   Wed, 15 Jan 2020 17:55:27 +0100

Cleanup

* Remove names filter when adding shortlinks
* Use Vue production version
* Small enhancements

Diffstat:
Madmin.php | 17++++-------------
Massets/main.js | 133++++++++++++++++++++++++++++++++++++++++---------------------------------------
2 files changed, 72 insertions(+), 78 deletions(-)

diff --git a/admin.php b/admin.php @@ -22,14 +22,6 @@ if (isset($_GET["get_data"])) { exit; } -// Filter the names that the admin interface doesn't break -function filter_name($nameRaw) { - $name = filter_var($nameRaw, FILTER_SANITIZE_STRING); - $name = str_replace(" ", "-", $name); - $name = preg_replace("/[^A-Za-z0-9-_]/", "", $name); - return $name; -} - // API functions to delete and add the shortlinks via the admin panel if (isset($_GET["delete"]) || isset($_GET["add"])) { $data = json_decode(file_get_contents("php://input"), true); @@ -37,7 +29,7 @@ if (isset($_GET["delete"]) || isset($_GET["add"])) { unset($config_content["shortlinks"][$data["name"]]); unset($stats_content[$data["name"]]); } else if (isset($_GET["add"])) { - $filtered = array("name" => filter_name($data["name"]), + $filtered = array("name" => filter_var($data["name"], FILTER_SANITIZE_STRING), "url" => filter_var($data["url"], FILTER_SANITIZE_URL)); if (!filter_var($filtered["url"], FILTER_VALIDATE_URL)) { echo "{\"status\": \"unvalid-url\"}"; @@ -136,7 +128,7 @@ if ($config_content["settings"]["custom_links"]) { <span class="sr-only">Loading...</span> </div> </div> - <chart v-for="(stats, name) in dataObject.stats" v-bind:key="name" :style="displayStyle(name)" v-bind:name="name" v-bind:stats="stats" v-else></chart> + <chart v-for="(stats, name) in dataObject.stats" v-bind:key="name" :style="displayStyle(name, shortlinkUrl)" v-bind:name="name" v-bind:stats="stats" v-else></chart> </div> </div> <p class="text-center d-md-none mt-1 mb-5" id="version-2">powered by <a href="https://github.com/flokX/devShort">devShort</a></p> @@ -171,7 +163,7 @@ if ($config_content["settings"]["custom_links"]) { </div> <hr> <p class="text-center text-muted mb-0" v-if="this.name === 'Index'">Index is an internal entry. It counts the number of front page accesses.</p> - <p class="text-center text-muted mb-0" v-else-if="this.name === '404-redirect'">404-redirect is an internal entry. It counts the number of 404 errors .</p> + <p class="text-center text-muted mb-0" v-else-if="this.name === '404-request'">404-request is an internal entry. It counts the number of accesses to non-existent shortlinks.</p> <div class="row" v-else> <div class="col-lg-9"> <label class="sr-only" :for="'destination-' + this.identifier">URL (destination)</label> @@ -192,8 +184,7 @@ if ($config_content["settings"]["custom_links"]) { </div> </template> - <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> - <!-- <script src="assets/vendor/vue/vue.min.js"></script> --> + <script src="assets/vendor/vue/vue.min.js"></script> <script src="assets/vendor/chart.js/Chart.bundle.min.js"></script> <script src="assets/vendor/hammer.js/hammer.min.js"></script> <script src="assets/vendor/chart.js/chartjs-plugin-zoom.min.js"></script> diff --git a/assets/main.js b/assets/main.js @@ -1,11 +1,70 @@ -/* Register variables */ +// Register variables const currentDate = new Date(); const spinner = document.getElementById('spinner'); -const chartsDiv = document.getElementById('charts'); const statusDiv = document.getElementById('status'); +const template = document.getElementById('chart-template'); const version = "v3.0.0"; +var chartOptions = { + type: 'bar', + data: { + datasets: [{ + label: 'Access count', + data: [], + backgroundColor: 'rgba(0, 123, 255, 0.4)', + borderColor: '#007bff', + hoverBackgroundColor: 'rgba(0, 123, 255, 0.7)' + }] + }, + options: { + legend: { + display: false + }, + title: { + display: true, + text: 'Accesses to ' + }, + scales: { + xAxes: [{ + type: 'time', + distribution: 'linear', + ticks: { + min: currentDate.getTime() - (60 * 60 * 24 * 14 * 1000), + max: currentDate + }, + time: { + tooltipFormat: 'YYYY-MM-DD', + unit: 'day' + } + }], + yAxes: [{ + ticks: { + beginAtZero: true, + precision: 0 + } + }] + }, + plugins: { + zoom: { + pan: { + enabled: true, + mode: 'x', + rangeMax: { + x: currentDate + } + }, + zoom: { + enabled: true, + mode: 'x', + rangeMax: { + x: currentDate + } + } + } + } + } +}; -/* Helper function to post to page api */ +// Helper function to post to page api function post(url, data) { 'use strict'; return fetch(url, { @@ -29,7 +88,7 @@ Vue.component('chart', { accessCount: { sevenDays: 0, total: 0 } } }, - template: document.getElementById('chart-template'), + template: template, mounted: function () { let ctx = document.getElementById(this.chartId); let dataset = []; @@ -41,65 +100,9 @@ Vue.component('chart', { dataset.push({ x: timestamp, y: count }); } this.accessCount.total = dataset.length; - this.chart = new Chart(ctx, { - type: 'bar', - data: { - datasets: [{ - label: 'Access count', - data: dataset, - backgroundColor: 'rgba(0, 123, 255, 0.4)', - borderColor: '#007bff', - hoverBackgroundColor: 'rgba(0, 123, 255, 0.7)' - }] - }, - options: { - legend: { - display: false - }, - title: { - display: true, - text: 'Accesses to ' + this.name - }, - scales: { - xAxes: [{ - type: 'time', - distribution: 'linear', - ticks: { - min: currentDate.getTime() - (60 * 60 * 24 * 14 * 1000), - max: currentDate - }, - time: { - tooltipFormat: 'YYYY-MM-DD', - unit: 'day' - } - }], - yAxes: [{ - ticks: { - beginAtZero: true, - precision: 0 - } - }] - }, - plugins: { - zoom: { - pan: { - enabled: true, - mode: 'x', - rangeMax: { - x: currentDate - } - }, - zoom: { - enabled: true, - mode: 'x', - rangeMax: { - x: currentDate - } - } - } - } - } - }); + this.chart = new Chart(ctx, chartOptions); + this.chart.data.datasets[0].data = dataset; + this.chart.options.title.text = 'Accesses to ' + this.name; }, beforeDestroy: function () { this.chart.destroy(); @@ -175,7 +178,7 @@ var vm = new Vue({ } }); -/* Add a new shortlink */ +// Add a new shortlink document.getElementById('add-form').addEventListener('submit', function (event) { 'use strict'; event.preventDefault(); @@ -195,7 +198,7 @@ document.getElementById('add-form').addEventListener('submit', function (event) }); }); -/* Check for updates */ +// Check for updates fetch('https://devshort.flokX.dev/api.php?mode=version&current=' + version).then(function (response) { return response.json(); }).then(function (json) {