commit 6c9cb54a71a0c02e84f4eeef7cf9e2f69682ec40
Author: Jan Pašek <janpasek97@gmail.com>
Date:   Sat Apr 3 16:17:52 2021 +0200

    Re #8475 - Added code comments

diff --git a/static/js/components.js b/static/js/components.js
index 54842aa..42b35f1 100644
--- a/static/js/components.js
+++ b/static/js/components.js
@@ -1,4 +1,7 @@
+
+// Component representing an instance in certificate listing
 Vue.component("certificate-item",{
+    // certificate = certificate to be displayed by the list item
     props: ["certificate"],
     template: "<tr>"+
                 "<td class='align-middle'>{{ certificate.CN }}</td>"+
@@ -15,6 +18,7 @@ Vue.component("certificate-item",{
                 "<td class='align-middle'><button v-on:click='onCertificateRootDownload()'>Download chain root</button></td>"+
             "</tr>",
     methods: {
+        // Get the certificate PEM data from the server and downloads it to users computer
         onCertificateDownload: function () {
             var id = this.certificate.id;
             axios.get(API_URL + "certificates/" + id)
@@ -29,6 +33,7 @@ Vue.component("certificate-item",{
                     console.log(error);
                 });
         },
+        // Get the certificate's chain of trust in PEM format from the server and downloads it to users computer
         onCertificateChainDownload: function () {
             var id = this.certificate.id;
             axios.get(API_URL + "certificates/" + id + "/chain")
@@ -43,6 +48,7 @@ Vue.component("certificate-item",{
                     console.log(error);
                 });
         },
+        // Get the certificate's root CA as PEM data from the server and downloads it to users computer
         onCertificateRootDownload: function () {
             var id = this.certificate.id;
             axios.get(API_URL + "certificates/" + id + "/root")
@@ -60,7 +66,9 @@ Vue.component("certificate-item",{
     }
 });
 
+// Component representing an item in select of available CAs
 Vue.component("ca-select-item", {
+    // Certificate authority to be represented by the option
     props: ["ca"],
     template: "<option v-bind:value='ca.id'>{{ ca.CN }}</option>"
 });
\ No newline at end of file
diff --git a/static/js/constants.js b/static/js/constants.js
index e921905..2e83ed4 100644
--- a/static/js/constants.js
+++ b/static/js/constants.js
@@ -1 +1,2 @@
+// API base url - in production it shall be only '/api/'
 const API_URL = "https://virtserver.swaggerhub.com/janpasek97/X509_management/1.0.0/api/";
\ No newline at end of file
diff --git a/static/js/create_certificate.js b/static/js/create_certificate.js
index b8dd7df..b9f6058 100644
--- a/static/js/create_certificate.js
+++ b/static/js/create_certificate.js
@@ -1,7 +1,11 @@
+
+    // VUE instance of certificate creation page
     var createCertificateApp = new Vue({
             el: "#create-certificate-content",
             data: {
-                authorities: [{id: 5, CN: "Test"}],
+                // available certificate authorities
+                authorities: [],
+                // data of the selected certificate authorities to be displayed in the form
                 selectedCAData: {
                     CN: "",
                     C:  "",
@@ -11,6 +15,7 @@
                     OU: "",
                     emailAddress: ""
                 },
+                // Data of the new certificate to be created received from the input fields
                 certificateData: {
                     subject: {
                         CN: "",
@@ -32,20 +37,36 @@
                     CA: null
                 }
             },
+            // actions to be performed when the page is loaded
+            // - initialize notBefore and notAfter with current date and current date + 1 month respectively
             mounted () {
-              this.certificateData.notBefore = new Date().toDateInputValue();
+              this.certificateData.notBefore = new Date().toDateInputValue(); // init notBefore to current date
               var endDate = new Date(new Date().getTime()+(30*24*60*60*1000));
-              this.certificateData.notAfter = endDate.toDateInputValue();
+              this.certificateData.notAfter = endDate.toDateInputValue(); // init notAfter to notBefore + 30 days
             },
             methods: {
+                // handle certificate creation request
                 onCreateCertificate: function () {
-
+                    // validate input data
+                    // - validate if subject CN is filled in
+                    if(this.certificateData.subject.CN === "") {
+                        alert("CN field must be filled in!"); // TODO highlight the field
+                        return;
+                    }
+                    // - validate if notAfter is > notBefore
+                    if(new Date(this.certificateData.notBefore) > new Date(this.certificateData.notAfter)) {
+                        alert("notBefore must chronologically lower than notAfter"); // TODO highlight the field
+                        return;
+                    }
+                    // send the request and handle response
                     axios.post(API_URL + "certificates", this.certificateData)
                         .then(function (response) {
+                            // on success return to index page
                             if(response.data["success"]) {
                                 alert("Certificate was successfully created.");
                                 window.location.href = "/static/index.html";
                             }
+                            // on error display server response message
                             else {
                                 alert(response.data["data"]);
                             }
@@ -55,8 +76,11 @@
                         });
                 }
             },
+            // data watches
             watch: {
+                // if the selected CA is changed, the Issuer input fileds must be filled in
                 'certificateData.CA': function (val, oldVal) {
+                    // self-signed certificate - all fields are empty
                     if (val === "null" || val == null) {
                         createCertificateApp.selectedCAData = {
                             CN: "",
@@ -68,6 +92,7 @@
                             emailAddress: ""
                         };
                     }
+                    // a CA is selected - get CA's details and display them
                     else {
                         axios.get(API_URL + "certificates/" + val + "/details")
                             .then(function (response) {
@@ -85,6 +110,7 @@
             }
         });
 
+    // Initialize available CA select values
     axios.get(API_URL+"certificates", {
             params: {
                 filtering: {
diff --git a/static/js/index.js b/static/js/index.js
index 586f109..94d348c 100644
--- a/static/js/index.js
+++ b/static/js/index.js
@@ -1,11 +1,14 @@
 
+    // certificate listing app VUE instance
     var certificateListingApp = new Vue({
         el: "#certificateListingPage",
         data: {
+            // list of all certificates to be displayed in the list
             certificates: []
         }
     });
 
+    // download a list of all available certificates and display them in the table
     axios.get(API_URL + "certificates")
         .then(function (response) {
             if (response.data["success"])
@@ -15,8 +18,4 @@
         })
         .catch(function (error) {
             console.log(error);
-        });
-
-    function downloadCertificate(id) {
-
-    }
\ No newline at end of file
+        });
\ No newline at end of file
diff --git a/static/js/utilities.js b/static/js/utilities.js
index 75066fb..03b5955 100644
--- a/static/js/utilities.js
+++ b/static/js/utilities.js
@@ -1,16 +1,26 @@
+/**
+ * Generate a file to be downloaded by the browser
+ * @param filename name of the file to be downloaded
+ * @param text content of the downloaded file
+ */
 function download(filename, text) {
-  var element = document.createElement('a');
-  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
-  element.setAttribute('download', filename);
+    // first a hidden <a> element is created and download content is assigned
+    var element = document.createElement('a');
+    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
+    element.setAttribute('download', filename);
 
-  element.style.display = 'none';
-  document.body.appendChild(element);
+    element.style.display = 'none';
+    document.body.appendChild(element);
 
-  element.click();
+    // generate artificial click event to download the file
+    element.click();
 
-  document.body.removeChild(element);
+    // remove the download link from the webpage
+    document.body.removeChild(element);
 }
 
+// Adds toDateInputValue() method to Date object
+// toDateInputValue() produces date in YYYY-MM-DD format
 Date.prototype.toDateInputValue = (function() {
     var local = new Date(this);
     local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
