devshort

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

main.js (4761B)


      1 // This file is part of the devShort project under the MIT License. Visit https://github.com/flokX/devShort for more information.
      2 
      3 // Register variables
      4 const currentDate = new Date();
      5 const startDate = new Date(new Date().setFullYear(currentDate.getFullYear() - 1));
      6 const spinner = document.getElementById('spinner');
      7 const template = document.getElementById('chart-template');
      8 const version = "v3.0.0";
      9 
     10 // Helper function to post to page api
     11 function post(url, data) {
     12     'use strict';
     13     return fetch(url, {
     14         method: 'POST',
     15         headers: {
     16             'Content-Type': 'application/json'
     17         },
     18         body: JSON.stringify(data)
     19     }).then(function (response) {
     20         return response.json();
     21     });
     22 }
     23 
     24 // Vue chart component
     25 Vue.component('chart', {
     26     props: ['name', 'stats'],
     27     data: function () {
     28         return {
     29             identifier: Math.floor(Math.random() * 10000),
     30             accessCount: { sevenDays: 0, total: 0 }
     31         }
     32     },
     33     template: template,
     34     methods: {
     35         render: function () {
     36             let dataset = [];
     37             this.accessCount = { sevenDays: 0, total: 0 };
     38             for (let [isoDate, count] of Object.entries(this.stats)) {
     39                 let date = new Date(isoDate);
     40                 if (((currentDate - date) / (60 * 60 * 24 * 1000)) <= 7) {
     41                     this.accessCount.sevenDays += count;
     42                 }
     43                 this.accessCount.total += count;
     44                 dataset.push({ x: date, y: count });
     45             }
     46             new frappe.Chart('div#' + this.chartId, {
     47                 type: 'heatmap',
     48                 title: 'Access statistics for ' + this.name,
     49                 data: {
     50                     dataPoints: this.stats,
     51                     start: startDate,
     52                     end: currentDate
     53                 },
     54                 countLabel: 'Accesses',
     55                 discreteDomains: 0
     56             });
     57         },
     58         remove: function (event) {
     59             post('admin.php?delete', {
     60                 name: this.name
     61             }).then(function (response) {
     62                 vm.loadData();
     63             });
     64         }
     65     },
     66     computed: {
     67         chartId: function () {
     68             return 'heatmap-' + this.identifier;
     69         },
     70         shortlinkUrl: function () {
     71             return this.$parent.dataObject.shortlinks[this.name];
     72         }
     73     },
     74     watch: {
     75         stats: function () {
     76             this.render();
     77         }
     78     },
     79     mounted: function () {
     80         this.render();
     81     }
     82 });
     83 
     84 // Vue app instance
     85 var vm = new Vue({
     86     el: '#app',
     87     data: {
     88         dataObject: [],
     89         loaded: false,
     90         search: ''
     91     },
     92     methods: {
     93         loadData: function (event) {
     94             if (event) {
     95                 // When calling this function via a card-link
     96                 event.preventDefault();
     97             }
     98             this.loaded = false;
     99             var vm = this;
    100             fetch('admin.php?get_data')
    101                 .then(function (response) {
    102                     return response.json()
    103                 })
    104                 .then(function (data) {
    105                     vm.dataObject = data
    106                 });
    107             this.loaded = true;
    108         },
    109         displayStyle: function (name) {
    110             if (!name.toLowerCase().includes(this.search.toLowerCase())) {
    111                 return 'display: none;'
    112             } else {
    113                 return 'display: block;'
    114             }
    115         }
    116     },
    117     created: function () {
    118         this.loadData();
    119     }
    120 });
    121 
    122 // Add a new shortlink
    123 document.getElementById('add-form').addEventListener('submit', function (event) {
    124     'use strict';
    125     event.preventDefault();
    126     post('admin.php?add', {
    127         name: document.getElementById('name').value,
    128         url: document.getElementById('url').value
    129     }).then(function (data) {
    130         if (data.status === 'successful') {
    131             document.getElementById('name').value = '';
    132             document.getElementById('url').value = 'https://';
    133             vm.loadData();
    134             document.getElementById('status').innerHTML = '';
    135         } else if (data.status === 'unvalid-url') {
    136             document.getElementById('status').insertAdjacentHTML('afterbegin', '<div class="alert alert-danger mt-2" role="alert">Unvalid URL. Please provide a valid URL.</div>');
    137         } else if (data.status === 'url-already-exists') {
    138             document.getElementById('status').insertAdjacentHTML('afterbegin', '<div class="alert alert-danger mt-2" role="alert">Shortlink already exists. Please delete before readding.</div>');
    139         } else {
    140             document.getElementById('status').insertAdjacentHTML('afterbegin', '<div class="alert alert-danger mt-2" role="alert">Error. Please try again.</div>');
    141         }
    142     });
    143 });