Skip to content

Commit

Permalink
Added: Sorting for hosts and Better Dropdowns with icons (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
Its4Nik authored Aug 27, 2024
1 parent 6f24c4d commit 0fc63fa
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 24 deletions.
30 changes: 27 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { toast, ToastContainer } from 'react-toastify';
import HostStats from './components/HostStats';
import ConfigFetcher from './components/ConfigFetcher';
Expand All @@ -10,14 +10,15 @@ import Loading from './components/Loading';
function App() {
const [data, setData] = useState({});
const [isInitialLoad, setIsInitialLoad] = useState(true);
const [intervalTime, setIntervalTime] = useState(10000);
const [theme, setTheme] = useState('');
const [intervalTime, setIntervalTime] = useState(10000);
const [loadingTheme, setLoadingTheme] = useState(false);
const [apihost, setApihost] = useState('');
const [apiKey, setApiKey] = useState('');
const [logoSize, setLogoSize] = useState('');
const [darkModeLogoColor, setDarkModeLogoColor] = useState('');
const [lightModeLogoColor, setLightModeLogoColor] = useState('');
const [sortOption, setSortOption] = useState('name-asc');

const handleConfigLoaded = (configData) => {
setApihost(configData.API_URL);
Expand All @@ -27,6 +28,27 @@ function App() {
setLightModeLogoColor(configData.LIGHT_MODE_LOGO_COLOR);
};

const sortHosts = (hostsData, option) => {
const sortedHosts = [...Object.keys(hostsData)].sort((a, b) => {
const aData = hostsData[a];
const bData = hostsData[b];

switch (option) {
case 'name-asc':
return a.localeCompare(b);
case 'name-desc':
return b.localeCompare(a);
case 'containers-asc':
return aData.length - bData.length;
case 'containers-desc':
return bData.length - aData.length;
default:
return 0;
}
});
return sortedHosts;
};

return (
<div className="container mx-auto p-4">
<ToastContainer />
Expand All @@ -37,6 +59,8 @@ function App() {
setIntervalTime={setIntervalTime}
theme={theme}
setTheme={setTheme}
sortOption={sortOption}
setSortOption={setSortOption}
/>
</div>
<ConfigFetcher onConfigLoaded={handleConfigLoaded} />
Expand All @@ -55,7 +79,7 @@ function App() {
<p className="text-center text-secondary text-small">If this screen persists, please check the browser console.</p>
</div>
) : (
Object.keys(data).map((host) => {
sortHosts(data, sortOption).map((host) => {
return (
<HostStats
key={host}
Expand Down
33 changes: 17 additions & 16 deletions src/components/Controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import React, { useState } from 'react';
import { FaGithub } from 'react-icons/fa';
import { IoSettingsOutline } from "react-icons/io5";
import { CSSTransition } from 'react-transition-group';
import './css/ModalAnimations.css'; // Import the CSS for animations
import SortDropdown from './dropdowns/SortDropdown';
import ThemeDropdown from './dropdowns/ThemeDropdown';
import './css/ModalAnimations.css';

const Controls = ({ intervalTime, setIntervalTime, theme, setTheme }) => {
const Controls = ({ intervalTime, setIntervalTime, theme, setTheme, sortOption, setSortOption }) => {
const [isModalOpen, setIsModalOpen] = useState(false);

const handleThemeChange = (e) => {
Expand Down Expand Up @@ -48,25 +50,15 @@ const Controls = ({ intervalTime, setIntervalTime, theme, setTheme }) => {
{/* Theme Selector */}
<div className="mb-4">
<h3 className="text-md font-medium mb-2">Select Theme</h3>
<select
className="select select-bordered w-full"
{/* <p>Current Theme: {theme}</p> */}
<ThemeDropdown
value={theme}
onChange={handleThemeChange}
>
<option value="light">☀️ - Light</option>^
<option value="nord">☀️ - Nord</option>
<option value="valentine">☀️ - Pastel</option>
<option value="business">🌙 - Business</option>
<option value="dracula">🌙 - Dracula</option>
<option value="sunset">🌙 - Sunset</option>
<option value="night">🌙 - Night</option>
<option value="forest">🌙 - Forest</option>
<option value="black">🌙 - Amoled</option>
</select>
/>
</div>

{/* Refresh Rate Selector */}
<div>
<div className="mb-4">
<h3 className="text-md font-medium mb-2">Select Refresh Rate</h3>
<select
className="select select-bordered w-full"
Expand All @@ -79,6 +71,15 @@ const Controls = ({ intervalTime, setIntervalTime, theme, setTheme }) => {
</select>
</div>

{/* Sort Selector */}
<div className="mb-4">
<h3 className="text-md font-medium mb-2">Sort Hosts By</h3>
<SortDropdown
value={sortOption}
onChange={(e) => setSortOption(e.target.value)}
/>
</div>

<button
className="btn btn-primary mt-6 w-full"
onClick={() => setIsModalOpen(false)}
Expand Down
17 changes: 14 additions & 3 deletions src/components/DataFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const fetchConfig = async () => {
}
};

const DataFetcher = ({ apihost, apiKey, setData, setIsInitialLoad, data }) => {
const DataFetcher = ({ apihost, apiKey, setData, setIsInitialLoad, data, sortBy }) => {
const [configData, setConfigData] = useState(null);
const [isInitialLoad, setInitialLoad] = useState(true);

Expand Down Expand Up @@ -41,7 +41,18 @@ const DataFetcher = ({ apihost, apiKey, setData, setIsInitialLoad, data }) => {
const result = await response.json();

if (JSON.stringify(result) !== JSON.stringify(data)) {
setData(result);
const sortedResult = Object.keys(result).sort((a, b) => {
// Default sort by host name
if (sortBy === 'name') {
return a.localeCompare(b);
}
// Add more sorting criteria if needed
return 0;
}).reduce((acc, key) => {
acc[key] = result[key];
return acc;
}, {});
setData(sortedResult);
}

if (isInitialLoad) {
Expand All @@ -56,7 +67,7 @@ const DataFetcher = ({ apihost, apiKey, setData, setIsInitialLoad, data }) => {
fetchData();
const interval = setInterval(fetchData, 5000); // intervalTime can be managed via props or state if necessary
return () => clearInterval(interval);
}, [apihost, apiKey, data, setData, setIsInitialLoad, configData, isInitialLoad]);
}, [apihost, apiKey, data, setData, setIsInitialLoad, configData, isInitialLoad, sortBy]);

return null; // This component does not render anything
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/ThemeSwitcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { themeChange } from 'theme-change';
const ThemeSwitcher = ({ theme }) => {
useEffect(() => {
themeChange(false);
document.querySelector('html').setAttribute('data-theme', theme); // Set theme attribute on the HTML tag
document.querySelector('html').setAttribute('data-theme', theme);
}, [theme]);

return null; // This component doesn't need to render anything
return null;
};

export default ThemeSwitcher;
28 changes: 28 additions & 0 deletions src/components/dropdowns/SortDropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { AiOutlineSortAscending, AiOutlineSortDescending } from "react-icons/ai";
import { TbSortDescendingNumbers, TbSortAscendingNumbers } from "react-icons/tb";

const ThemeDropdown = ({ value, onChange }) => {
return (
<div className="relative inline-block w-full">
<select
className="select select-bordered w-full pr-12"
value={value}
onChange={onChange}
>
<option value="name-asc">Name Ascending</option>
<option value="name-desc">Name Descending</option>
<option value="containers-asc">Container Amount Ascending</option>
<option value="containers-desc">Container Amount Descending</option>
</select>
<div className="absolute inset-y-0 right-0 flex items-center mr-5 pr-3 pointer-events-none">
{value === 'name-asc' && <AiOutlineSortAscending className="text-xl" />}
{value === 'name-desc' && <AiOutlineSortDescending className="text-xl" />}
{value === 'containers-asc' && <TbSortAscendingNumbers className="text-xl" />}
{value === 'containers-desc' && <TbSortDescendingNumbers className="text-xl" />}
</div>
</div>
);
};

export default ThemeDropdown;
39 changes: 39 additions & 0 deletions src/components/dropdowns/ThemeDropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { FaRegSun, FaRegMoon } from "react-icons/fa";


const SortDropdown = ({ value, onChange }) => {
return (
<div className="relative inline-block w-full">
<select
className="select select-bordered w-full pr-12"
value={value}
onChange={onChange}
>
<option value="light">Light</option>
<option value="nord">Nord</option>
<option value="valentine">Pastel</option>
<option value="business">Business</option>
<option value="dracula">Dracula</option>
<option value="sunset">Sunset</option>
<option value="night">Night</option>
<option value="forest">Forest</option>
<option value="black">Amoled</option>
</select>
<div className="absolute inset-y-0 right-0 flex items-center mr-5 pr-3 pointer-events-none">
{value === '' && <FaRegSun className="text-xl" />}
{value === 'light' && <FaRegSun className="text-xl" />}
{value === 'nord' && <FaRegSun className="text-xl" />}
{value === 'valentine' && <FaRegSun className="text-xl" />}
{value === 'business' && <FaRegMoon className="text-xl" />}
{value === 'dracula' && <FaRegMoon className="text-xl" />}
{value === 'sunset' && <FaRegMoon className="text-xl" />}
{value === 'night' && <FaRegMoon className="text-xl" />}
{value === 'forest' && <FaRegMoon className="text-xl" />}
{value === 'black' && <FaRegMoon className="text-xl" />}
</div>
</div>
);
};

export default SortDropdown;

0 comments on commit 0fc63fa

Please sign in to comment.