From ac5e4e36c30c79c30e050f0402ecf989d94a8b9f Mon Sep 17 00:00:00 2001
From: Tin Geber <tin@greenhost.nl>
Date: Fri, 2 Jun 2023 13:42:59 +0200
Subject: [PATCH] moved UpdateAlert and VersionInfo to components

---
 .gitignore                                    |   1 +
 frontend/src/modules/dashboard/Dashboard.tsx  | 141 +-----------------
 .../components/UpdateAlert/UpdateAlert.tsx    |  41 +++++
 .../dashboard/components/UpdateAlert/index.ts |   1 +
 .../components/VersionInfo/VersionInfo.tsx    |  94 ++++++++++++
 .../dashboard/components/VersionInfo/index.ts |   1 +
 .../src/modules/dashboard/components/index.ts |   2 +
 .../src/modules/dashboard/systemInfo.json     |  15 --
 8 files changed, 143 insertions(+), 153 deletions(-)
 create mode 100644 frontend/src/modules/dashboard/components/UpdateAlert/UpdateAlert.tsx
 create mode 100644 frontend/src/modules/dashboard/components/UpdateAlert/index.ts
 create mode 100644 frontend/src/modules/dashboard/components/VersionInfo/VersionInfo.tsx
 create mode 100644 frontend/src/modules/dashboard/components/VersionInfo/index.ts
 delete mode 100644 frontend/src/modules/dashboard/systemInfo.json

diff --git a/.gitignore b/.gitignore
index f3e8370a..b6fc8ae0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@
 
 # local environment
 /frontend/local.env
+/.vscode
 
 # misc
 .DS_Store
diff --git a/frontend/src/modules/dashboard/Dashboard.tsx b/frontend/src/modules/dashboard/Dashboard.tsx
index 20a5b548..43468610 100644
--- a/frontend/src/modules/dashboard/Dashboard.tsx
+++ b/frontend/src/modules/dashboard/Dashboard.tsx
@@ -10,20 +10,7 @@ import React, { useEffect } from 'react';
 import { useApps } from 'src/services/apps';
 import { useSysInfo } from 'src/services/sysInfo';
 import { AppStatusEnum } from 'src/services/apps/types';
-import { Popover, Transition } from '@headlessui/react';
-import {
-  CheckCircleIcon,
-  NewspaperIcon,
-  SparklesIcon,
-  LightningBoltIcon,
-  ChevronDownIcon,
-  CalendarIcon,
-  BeakerIcon,
-  HomeIcon,
-  RefreshIcon,
-} from '@heroicons/react/outline';
-// import systemInfo from './systemInfo.json';
-import { DashboardCard, DashboardUtility } from './components';
+import { DashboardCard, DashboardUtility, UpdateAlert, VersionInfo } from './components';
 import { DASHBOARD_QUICK_ACCESS, HIDDEN_APPS, UTILITY_APPS } from './consts';
 
 export const Dashboard: React.FC = () => {
@@ -43,140 +30,19 @@ export const Dashboard: React.FC = () => {
 
   const appVersions = { ...sysInfo.sysInfo.appVersions };
 
-  const updateTime: Date = new Date(sysInfo.sysInfo.lastUpdated);
-  const hoursSinceUpdate = Math.floor((new Date().getTime() - updateTime.getTime()) / 3600000);
-
-  // manual toggles to test alert bar
-  // const hoursSinceUpdate = 21;
-
-  // const lastRelease = sysInfo.sysInfo.lastRelease;
-
-  const updateStatus =
-    sysInfo.sysInfo.lastRelease > sysInfo.sysInfo.version ? 'imminent' : hoursSinceUpdate <= 24 ? 'updated' : 'no';
-
-  // the update alert box has two states: when the latest version
-  // on the v2 branch is more recent than the current one, the yellow alert bar
-  // shows that an update will happen in the next 24 hours.
-  // After the update, a green alert bar shows with a success message
-  // and stays there for 24 hours
-  const updateAlert = (status: string) =>
-    status === 'imminent' ? (
-      <div className="update-alert w-full h-5 py-3 bg-yellow-100 flex items-center justify-center text-xs font-medium text-gray-500 gap-2">
-        <LightningBoltIcon className="h-4 w-4 text-primary-800" />
-        <p>Attention: your Stackspin instance will be updated in the next 24 hours. </p>
-        <a
-          className="hover:text-primary-500 underline"
-          href={sysInfo.sysInfo.releaseNotesUrl}
-          target="_blank"
-          rel="noreferrer noopener"
-        >
-          Explore new features <NewspaperIcon className="h-4 w-4 inline" />
-        </a>
-      </div>
-    ) : status === 'updated' ? (
-      <div className="update-alert w-full h-5 py-3 bg-primary-200 flex items-center justify-center text-xs font-medium text-primary-700 gap-2">
-        <SparklesIcon className="h-4 w-4 text-primary-800" />
-        <p>Your Stackspin just got an update!</p>
-        <a
-          className="hover:text-primary-500 underline"
-          href={sysInfo.sysInfo.releaseNotesUrl}
-          target="_blank"
-          rel="noreferrer noopener"
-        >
-          See what&apos;s new <NewspaperIcon className="h-4 w-4 inline" />
-        </a>
-      </div>
-    ) : null;
-
-  const branch = sysInfo.sysInfo.followingGit;
-
-  // eslint-disable-next-line
-  // let branch = 'DF234FD';
-  const knownMainBranch = 'v2';
-
-  const versionInfo =
-    branch === knownMainBranch ? (
-      <>
-        <CheckCircleIcon className="h-4 w-4 text-primary-600" />
-        <span>Stackspin v{sysInfo.sysInfo.version}</span>
-      </>
-    ) : branch !== knownMainBranch ? (
-      <>
-        <span>Stackspin v{sysInfo.sysInfo.version}</span>
-      </>
-    ) : null;
-
-  const updatesText =
-    branch === knownMainBranch ? (
-      <>
-        <div className="px-4 py-2 flex items-center gap-1">
-          <HomeIcon className="w-4 h-4 text-gray-500" />
-          <span>Using main branch ({branch})</span>
-        </div>
-        <div className="px-4 py-2 flex items-center gap-1">
-          <RefreshIcon className="w-4 h-4 text-gray-500" />
-          <span>Automatic updates active</span>
-        </div>
-      </>
-    ) : branch !== knownMainBranch ? (
-      <div className="px-4 py-2 flex items-center gap-1">
-        <BeakerIcon className="w-4 h-4 text-gray-500" />
-        <span>Custom branch ({branch})</span>
-      </div>
-    ) : null;
-
   return (
     <div className="relative">
-      {updateAlert(updateStatus)}
+      <UpdateAlert sysInfo={sysInfo.sysInfo} />
       <div className="max-w-7xl mx-auto py-4 px-3 sm:px-6 lg:px-8">
         <div className="mt-6 pb-5 border-b border-gray-200 sm:flex sm:items-center sm:justify-between">
           <h1 className="text-3xl leading-6 font-bold text-gray-900">Dashboard</h1>
           <div className="system-status text-xs font-medium text-gray-500 flex flex-col gap-2">
             <div className="flex items-center gap-1">
-              <Popover className="relative flex items-center">
-                <Popover.Button className="flex text-sm px-2.5 py-1.5 group items-center gap-1 border border-transparent hover:shadow-sm focus:shadow-sm font-medium rounded-md text-gray-500 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
-                  {versionInfo}
-                  <ChevronDownIcon className="h-4 w-4 text-primary-800" />
-                </Popover.Button>
-                <Transition
-                  enter="transition ease-out duration-200"
-                  enterFrom="transform opacity-0 scale-95"
-                  enterTo="transform opacity-100 scale-100"
-                  leave="transition ease-in duration-75"
-                  leaveFrom="transform opacity-100 scale-100"
-                  leaveTo="transform opacity-0 scale-95"
-                >
-                  <Popover.Panel className="absolute z-10 origin-top-right right-0 top-5 mt-2  rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
-                    <div className="flex flex-col items-stretch p-4 w-60 divide-y divide-gray-100 text-xs text-gray-500">
-                      {updatesText}
-                      <div className="px-4 py-2 flex items-center gap-1">
-                        <NewspaperIcon className="h-4 w-4 text-gray-500" />
-                        <a
-                          className="hover:text-primary-500 underline"
-                          href={sysInfo.sysInfo.releaseNotesUrl}
-                          target="_blank"
-                          rel="noreferrer noopener"
-                        >
-                          Changelog
-                        </a>
-                      </div>
-                      <div className="px-4 py-2 flex items-center gap-1">
-                        <CalendarIcon className="h-4 w-4 text-gray-500" />
-                        <span>Last update:</span>
-                        <span>
-                          {/* {updateTime.getDate()}.{updateTime.getMonth()} {updateTime.getFullYear()} */}
-                          {updateTime.toLocaleDateString('en-uk', { day: 'numeric', year: 'numeric', month: 'short' })}
-                        </span>
-                      </div>
-                    </div>
-                  </Popover.Panel>
-                </Transition>
-              </Popover>
+              <VersionInfo sysInfo={sysInfo.sysInfo} />
             </div>
           </div>
         </div>
       </div>
-
       <div className="max-w-7xl mx-auto py-4 px-3 sm:px-6 lg:px-8 h-full flex-grow">
         <div className="grid grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-4 mb-10">
           {apps
@@ -191,7 +57,6 @@ export const Dashboard: React.FC = () => {
           <div className="pb-4 border-b border-gray-200 sm:flex sm:items-center">
             <h3 className="text-lg leading-6 font-medium text-gray-900">Utilities</h3>
           </div>
-
           <dl className="mt-5 grid grid-cols-1 gap-2 sm:grid-cols-2">
             {DASHBOARD_QUICK_ACCESS.map((item) => (
               <DashboardUtility item={item} key={item.name} />
diff --git a/frontend/src/modules/dashboard/components/UpdateAlert/UpdateAlert.tsx b/frontend/src/modules/dashboard/components/UpdateAlert/UpdateAlert.tsx
new file mode 100644
index 00000000..d2407196
--- /dev/null
+++ b/frontend/src/modules/dashboard/components/UpdateAlert/UpdateAlert.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import { LightningBoltIcon, NewspaperIcon, SparklesIcon } from '@heroicons/react/outline';
+import { SysInfoState } from 'src/services/sysInfo/redux/types';
+
+export const UpdateAlert = (sysInfo: SysInfoState) => {
+  const updateTime: Date = new Date(sysInfo.sysInfo.lastUpdated);
+  const hoursSinceUpdate = Math.floor((new Date().getTime() - updateTime.getTime()) / 3600000);
+  const updateStatus: string =
+    sysInfo.sysInfo.lastRelease > sysInfo.sysInfo.version ? 'imminent' : hoursSinceUpdate <= 24 ? 'updated' : 'no';
+
+  const updateAlert = (status: string) =>
+    status === 'imminent' ? (
+      <div className="update-alert w-full h-5 py-3 bg-yellow-100 flex items-center justify-center text-xs font-medium text-gray-500 gap-2">
+        <LightningBoltIcon className="h-4 w-4 text-primary-800" />
+        <p>Attention: your Stackspin instance will be updated in the next 24 hours. </p>
+        <a
+          className="hover:text-primary-500 underline"
+          href={sysInfo.sysInfo.releaseNotesUrl}
+          target="_blank"
+          rel="noreferrer noopener"
+        >
+          Explore new features <NewspaperIcon className="h-4 w-4 inline" />
+        </a>
+      </div>
+    ) : status === 'updated' ? (
+      <div className="update-alert w-full h-5 py-3 bg-primary-200 flex items-center justify-center text-xs font-medium text-primary-700 gap-2">
+        <SparklesIcon className="h-4 w-4 text-primary-800" />
+        <p>Your Stackspin just got an update!</p>
+        <a
+          className="hover:text-primary-500 underline"
+          href={sysInfo.sysInfo.releaseNotesUrl}
+          target="_blank"
+          rel="noreferrer noopener"
+        >
+          See what&apos;s new <NewspaperIcon className="h-4 w-4 inline" />
+        </a>
+      </div>
+    ) : null;
+
+  return <>{updateAlert('imminent')}</>;
+};
diff --git a/frontend/src/modules/dashboard/components/UpdateAlert/index.ts b/frontend/src/modules/dashboard/components/UpdateAlert/index.ts
new file mode 100644
index 00000000..3a64428b
--- /dev/null
+++ b/frontend/src/modules/dashboard/components/UpdateAlert/index.ts
@@ -0,0 +1 @@
+export { UpdateAlert } from './UpdateAlert';
diff --git a/frontend/src/modules/dashboard/components/VersionInfo/VersionInfo.tsx b/frontend/src/modules/dashboard/components/VersionInfo/VersionInfo.tsx
new file mode 100644
index 00000000..20e6246b
--- /dev/null
+++ b/frontend/src/modules/dashboard/components/VersionInfo/VersionInfo.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import { Popover, Transition } from '@headlessui/react';
+import {
+  CheckCircleIcon,
+  NewspaperIcon,
+  ChevronDownIcon,
+  CalendarIcon,
+  BeakerIcon,
+  HomeIcon,
+  RefreshIcon,
+} from '@heroicons/react/outline';
+import { SysInfoState } from 'src/services/sysInfo/redux/types';
+
+export const VersionInfo = (sysInfo: SysInfoState) => {
+  const branch = sysInfo.sysInfo.followingGit;
+  const updateTime: Date = new Date(sysInfo.sysInfo.lastUpdated);
+
+  // eslint-disable-next-line
+  // let branch = 'DF234FD';
+  const knownMainBranch = 'v2';
+
+  const versionInfo =
+    branch === knownMainBranch ? (
+      <>
+        <CheckCircleIcon className="h-4 w-4 text-primary-600" />
+        <span>Stackspin v{sysInfo.sysInfo.version}</span>
+      </>
+    ) : branch !== knownMainBranch ? (
+      <>
+        <span>Stackspin v{sysInfo.sysInfo.version}</span>
+      </>
+    ) : null;
+
+  const updatesText =
+    branch === knownMainBranch ? (
+      <>
+        <div className="px-4 py-2 flex items-center gap-1">
+          <HomeIcon className="w-4 h-4 text-gray-500" />
+          <span>Using main branch ({branch})</span>
+        </div>
+        <div className="px-4 py-2 flex items-center gap-1">
+          <RefreshIcon className="w-4 h-4 text-gray-500" />
+          <span>Automatic updates active</span>
+        </div>
+      </>
+    ) : branch !== knownMainBranch ? (
+      <div className="px-4 py-2 flex items-center gap-1">
+        <BeakerIcon className="w-4 h-4 text-gray-500" />
+        <span>Custom branch ({branch})</span>
+      </div>
+    ) : null;
+
+  return (
+    <Popover className="relative flex items-center">
+      <Popover.Button className="flex text-sm px-2.5 py-1.5 group items-center gap-1 border border-transparent hover:shadow-sm focus:shadow-sm font-medium rounded-md text-gray-500 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
+        {versionInfo}
+        <ChevronDownIcon className="h-4 w-4 text-primary-800" />
+      </Popover.Button>
+      <Transition
+        enter="transition ease-out duration-200"
+        enterFrom="transform opacity-0 scale-95"
+        enterTo="transform opacity-100 scale-100"
+        leave="transition ease-in duration-75"
+        leaveFrom="transform opacity-100 scale-100"
+        leaveTo="transform opacity-0 scale-95"
+      >
+        <Popover.Panel className="absolute z-10 origin-top-right right-0 top-5 mt-2  rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
+          <div className="flex flex-col items-stretch p-4 w-60 divide-y divide-gray-100 text-xs text-gray-500">
+            {updatesText}
+            <div className="px-4 py-2 flex items-center gap-1">
+              <NewspaperIcon className="h-4 w-4 text-gray-500" />
+              <a
+                className="hover:text-primary-500 underline"
+                href={sysInfo.sysInfo.releaseNotesUrl}
+                target="_blank"
+                rel="noreferrer noopener"
+              >
+                Changelog
+              </a>
+            </div>
+            <div className="px-4 py-2 flex items-center gap-1">
+              <CalendarIcon className="h-4 w-4 text-gray-500" />
+              <span>Last update:</span>
+              <span>
+                {/* {updateTime.getDate()}.{updateTime.getMonth()} {updateTime.getFullYear()} */}
+                {updateTime.toLocaleDateString('en-uk', { day: 'numeric', year: 'numeric', month: 'short' })}
+              </span>
+            </div>
+          </div>
+        </Popover.Panel>
+      </Transition>
+    </Popover>
+  );
+};
diff --git a/frontend/src/modules/dashboard/components/VersionInfo/index.ts b/frontend/src/modules/dashboard/components/VersionInfo/index.ts
new file mode 100644
index 00000000..d573df80
--- /dev/null
+++ b/frontend/src/modules/dashboard/components/VersionInfo/index.ts
@@ -0,0 +1 @@
+export { VersionInfo } from './VersionInfo';
diff --git a/frontend/src/modules/dashboard/components/index.ts b/frontend/src/modules/dashboard/components/index.ts
index 2a146829..db323609 100644
--- a/frontend/src/modules/dashboard/components/index.ts
+++ b/frontend/src/modules/dashboard/components/index.ts
@@ -1,2 +1,4 @@
 export { DashboardCard } from './DashboardCard';
 export { DashboardUtility } from './DashboardUtility';
+export { UpdateAlert } from './UpdateAlert';
+export { VersionInfo } from './VersionInfo';
diff --git a/frontend/src/modules/dashboard/systemInfo.json b/frontend/src/modules/dashboard/systemInfo.json
deleted file mode 100644
index 70b1928d..00000000
--- a/frontend/src/modules/dashboard/systemInfo.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "appVersions": {
-    "dashboard": "0.6.5",
-    "nextcloud": "25.0.4",
-    "velero": "1.9.4",
-    "wekan": "5.93",
-    "wordpress": "6.0.1",
-    "zulip": "6.0",
-    "hedgedoc": "4.2"
-  },
-  "lastRelease": "2.4",
-  "lastUpdated": "2023-03-16T11:41:24Z",
-  "releaseNotesUrl": "https://open.greenhost.net/stackspin/stackspin/-/blob/main/CHANGELOG.md#anchor-24",
-  "version": "2.4"
-}
-- 
GitLab