From cf2113e77edabf8e3a632c7b76c769752039ba88 Mon Sep 17 00:00:00 2001
From: Zach Berwaldt <zberwaldt@tutamail.com>
Date: Sat, 2 Mar 2024 16:52:55 -0500
Subject: feat: Add API logging

Add logging to the API to keep track of specific requests and headers. Also added CORS middleware to handle OPTIONS requests.

---

The commit adds logging functionality to the API and includes a middleware function to handle CORS OPTIONS requests. This will allow us to track specific requests and headers received by the API.

[API/main.go](/api/main.go):
- Added import for the 'log' package
- Added logging statements to print the request headers and "_I am here_" message
- Removed unnecessary newlines and comments

[fe/src/app.css](/fe/src/app.css):
- Added a new style for button hover effects

[fe/src/lib/Card.svelte](/fe/src/lib/Card.svelte):
- Added a new `height` prop to the Card component

[fe/src/lib/Column.svelte](/fe/src/lib/Column.svelte):
- Added a new CSS class for column layout
- Set the width and gap using CSS variables

[fe/src/lib/DataView.svelte](/fe/src/lib/DataView.svelte):
- Updated the 'fetchData' function to also fetch 'totals' and 'userStats' data
- Added canvas references and chart variables for bar and line charts
- Added a new 'getLastSevenDays' function to calculate the labels for the charts
- Updated the 'onMount' function to initialize the bar and line charts using the canvas references and data
- Updated the 'onDestroy' function to destroy the bar and line charts
- Added a new 'addFormOpen' store and imported it
- Added a new 'onClick' handler for the Add button to open the AddForm modal
- Updated the layout and added Card components to display the bar and line charts and the JSON data
- Added a new 'fetchTotals' function to fetch data for the 'totals' section
- Added a new 'fetchStatsForUser' function to fetch data for the 'userStats' section

[fe/src/lib/Layout.svelte](/fe/src/lib/Layout.svelte):
- Added a new 'preferenceFormOpen' variable and initialized it to 'false'
- Added a new 'showPreferencesDialog' function to set 'preferenceFormOpen' to 'true'
- Added a new 'closePreferenceDialog' function to set 'preferenceFormOpen' to 'false'
- Added a new 'showAddDialog' function to open the AddForm modal
---
 fe/src/lib/Table.svelte | 172 +++++++++++++++++++++++++-----------------------
 1 file changed, 90 insertions(+), 82 deletions(-)

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
index 3a66e0d..d1cd7da 100644
--- a/fe/src/lib/Table.svelte
+++ b/fe/src/lib/Table.svelte
@@ -1,105 +1,113 @@
 <script lang="ts">
-  export let data: Array<any> | undefined = undefined;
-  export let nofooter: boolean = false;
-  export let noheader: boolean = false;
-  export let omit: string[] = ["id"];
-  export let title: string | undefined = undefined;
+    export let data: Array<any> | undefined = undefined;
+    export let nofooter: boolean = false;
+    export let noheader: boolean = false;
+    export let omit: string[] = ["id"];
+    export let title: string | undefined = undefined;
 
-  function getDataKeys(data: any[]): string[] {
-    if (!data || data.length === 0) return [];
-    return Object.keys(data[0])
-      .map((k) => k.split("_").join(" "))
-      .filter((k) => !omit.includes(k));
-  }
+    function getDataKeys(data: any[]): string[] {
+        if (!data || data.length === 0) return [];
+        return Object.keys(data[0])
+            .map((k) => k.split("_").join(" "))
+            .filter((k) => !omit.includes(k));
+    }
 
-  function getRow(row: Record<string, any>): Array<any> {
-    return Object.entries(row).filter((r) => !omit.includes(r[0]));
-  }
+    function getRow(row: Record<string, any>): Array<any> {
+        return Object.entries(row).filter((r) => !omit.includes(r[0]));
+    }
 
-  const formatter = new Intl.DateTimeFormat("en", {
-    year: "numeric",
-    month: "numeric",
-    day: "numeric",
-    hour: "numeric",
-    minute: "2-digit",
-    second: "2-digit",
-    timeZone: "America/New_York",
-  });
 
-  function formatDatum([key, value]: any[]) {
-    if (key === "date") {
-      const parsedDate = new Date(value);
-      return formatter.format(parsedDate);
-    }
+    let limitedData: Array<any> = [];
 
-    if (key === "user") {
-      return value["name"];
+    if (data && (data as any[]).length > 0) {
+        limitedData = (data as any[]).slice(0, 4);
     }
 
-    return value;
-  }
+    const formatter = new Intl.DateTimeFormat("en", {
+        year: "numeric",
+        month: "numeric",
+        day: "numeric",
+        hour: "numeric",
+        minute: "2-digit",
+        second: "2-digit",
+        timeZone: "America/New_York"
+    });
+
+    function formatDatum([key, value]: any[]) {
+        if (key === "date") {
+            const parsedDate = new Date(value);
+            return formatter.format(parsedDate);
+        }
+
+        if (key === "user") {
+            return value["name"];
+        }
+
+        return value;
+    }
 </script>
 
 <table>
-  {#if title}
-    <h2>{title}</h2>
-  {/if}
-  {#if !noheader && data}
-    <thead>
-      <tr>
-        {#each getDataKeys(data) as header}
-          <th>{header}</th>
-        {/each}
-      </tr>
-    </thead>
-  {/if}
-  <tbody>
-    {#if data}
-      {#each data as row}
+    {#if title}
+        <h2>{title}</h2>
+    {/if}
+    {#if !noheader && data}
+        <thead>
         <tr>
-          {#each getRow(row) as datum}
-            <td>{formatDatum(datum)}</td>
-          {/each}
+            {#each getDataKeys(data) as header}
+                <th>{header}</th>
+            {/each}
         </tr>
-      {/each}
+        </thead>
+    {/if}
+    <tbody>
+    {#if data}
+        {#each limitedData as row}
+            <tr>
+                {#each getRow(row) as datum}
+                    <td>{formatDatum(datum)}</td>
+                {/each}
+            </tr>
+        {/each}
     {:else}
-      <tr> There is not data. </tr>
+        <tr> There is not data.</tr>
+    {/if}
+    </tbody>
+    {#if !nofooter}
+        <slot name="footer">
+            <tfoot>
+            <tr>
+                <td>Table Footer</td>
+            </tr>
+            </tfoot>
+        </slot>
     {/if}
-  </tbody>
-  {#if !nofooter}
-    <slot name="footer">
-      <tfoot>
-        <tr>
-          <td>Table Footer</td>
-        </tr>
-      </tfoot>
-    </slot>
-  {/if}
 </table>
 
 <style>
-  table {
-    padding: 16px;
-    margin: 8px;
-    border: solid 1px black;
-    border-collapse: collapse;
-  }
+    table {
+        padding: 16px;
+        margin: 8px;
+        border: solid 1px black;
+        border-collapse: collapse;
+        overflow-y: hidden;
+    }
 
-  th {
-    text-transform: capitalize;
-  }
+    th {
+        text-transform: capitalize;
+    }
 
-  thead tr {
-    background: rgba(0, 0, 23, 0.34);
-  }
+    thead tr {
+        background: rgba(0, 0, 23, 0.34);
+    }
 
-  tbody tr:nth-child(odd) {
-    background: rgba(0, 0, 23, 0.14);
-  }
+    tbody tr:nth-child(odd) {
+        background: rgba(0, 0, 23, 0.14);
+    }
 
-  th,
-  td {
-    padding: 1em;
-    border: 1px solid rgba(0, 0, 0, 1);
-  }
+    th,
+    td {
+        padding: 1em;
+        border: 1px solid rgba(0, 0, 0, 1);
+    }
 </style>
-- 
cgit v1.1

