fix(frontend): add missing explicit types for button elems

This commit is contained in:
tigattack
2025-09-24 22:19:26 +01:00
parent 35bf858977
commit a11f180d23
16 changed files with 158 additions and 5 deletions

View File

@@ -75,6 +75,7 @@ const SortableCardItem = ({ card, onToggle }) => {
</div> </div>
<button <button
type="button"
onClick={() => onToggle(card.cardId)} onClick={() => onToggle(card.cardId)}
className={`flex items-center gap-1 px-2 py-1 rounded text-xs font-medium transition-colors ${ className={`flex items-center gap-1 px-2 py-1 rounded text-xs font-medium transition-colors ${
card.enabled card.enabled
@@ -271,6 +272,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
</h3> </h3>
</div> </div>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >
@@ -314,6 +316,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
<div className="bg-secondary-50 dark:bg-secondary-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> <div className="bg-secondary-50 dark:bg-secondary-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button <button
type="button"
onClick={handleSave} onClick={handleSave}
disabled={!hasChanges || updatePreferencesMutation.isPending} disabled={!hasChanges || updatePreferencesMutation.isPending}
className={`w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 text-base font-medium text-white sm:ml-3 sm:w-auto sm:text-sm ${ className={`w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 text-base font-medium text-white sm:ml-3 sm:w-auto sm:text-sm ${
@@ -336,6 +339,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
</button> </button>
<button <button
type="button"
onClick={handleReset} onClick={handleReset}
className="mt-3 w-full inline-flex justify-center rounded-md border border-secondary-300 dark:border-secondary-600 shadow-sm px-4 py-2 bg-white dark:bg-secondary-800 text-base font-medium text-secondary-700 dark:text-secondary-200 hover:bg-secondary-50 dark:hover:bg-secondary-700 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" className="mt-3 w-full inline-flex justify-center rounded-md border border-secondary-300 dark:border-secondary-600 shadow-sm px-4 py-2 bg-white dark:bg-secondary-800 text-base font-medium text-secondary-700 dark:text-secondary-200 hover:bg-secondary-50 dark:hover:bg-secondary-700 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
> >
@@ -344,6 +348,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
</button> </button>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="mt-3 w-full inline-flex justify-center rounded-md border border-secondary-300 dark:border-secondary-600 shadow-sm px-4 py-2 bg-white dark:bg-secondary-800 text-base font-medium text-secondary-700 dark:text-secondary-200 hover:bg-secondary-50 dark:hover:bg-secondary-700 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" className="mt-3 w-full inline-flex justify-center rounded-md border border-secondary-300 dark:border-secondary-600 shadow-sm px-4 py-2 bg-white dark:bg-secondary-800 text-base font-medium text-secondary-700 dark:text-secondary-200 hover:bg-secondary-50 dark:hover:bg-secondary-700 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
> >

View File

@@ -102,6 +102,7 @@ const InlineEdit = ({
} ${isLoading ? "opacity-50" : ""}`} } ${isLoading ? "opacity-50" : ""}`}
/> />
<button <button
type="button"
onClick={handleSave} onClick={handleSave}
disabled={isLoading || editValue.trim() === ""} disabled={isLoading || editValue.trim() === ""}
className="p-1 text-green-600 hover:text-green-700 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed" className="p-1 text-green-600 hover:text-green-700 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
@@ -110,6 +111,7 @@ const InlineEdit = ({
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</button> </button>
<button <button
type="button"
onClick={handleCancel} onClick={handleCancel}
disabled={isLoading} disabled={isLoading}
className="p-1 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed" className="p-1 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
@@ -145,6 +147,7 @@ const InlineEdit = ({
{displayValue} {displayValue}
{!disabled && ( {!disabled && (
<button <button
type="button"
onClick={handleEdit} onClick={handleEdit}
className="p-1 text-secondary-400 hover:text-secondary-600 dark:hover:text-secondary-300 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded transition-colors opacity-0 group-hover:opacity-100" className="p-1 text-secondary-400 hover:text-secondary-600 dark:hover:text-secondary-300 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded transition-colors opacity-0 group-hover:opacity-100"
title="Edit" title="Edit"

View File

@@ -221,6 +221,7 @@ const InlineGroupEdit = ({
)} )}
</div> </div>
<button <button
type="button"
onClick={handleSave} onClick={handleSave}
disabled={isLoading} disabled={isLoading}
className="p-1 text-green-600 hover:text-green-700 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed" className="p-1 text-green-600 hover:text-green-700 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
@@ -229,6 +230,7 @@ const InlineGroupEdit = ({
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
</button> </button>
<button <button
type="button"
onClick={handleCancel} onClick={handleCancel}
disabled={isLoading} disabled={isLoading}
className="p-1 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed" className="p-1 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
@@ -256,6 +258,7 @@ const InlineGroupEdit = ({
</span> </span>
{!disabled && ( {!disabled && (
<button <button
type="button"
onClick={handleEdit} onClick={handleEdit}
className="p-1 text-secondary-400 hover:text-secondary-600 dark:hover:text-secondary-300 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded transition-colors opacity-0 group-hover:opacity-100" className="p-1 text-secondary-400 hover:text-secondary-600 dark:hover:text-secondary-300 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded transition-colors opacity-0 group-hover:opacity-100"
title="Edit group" title="Edit group"

View File

@@ -386,6 +386,7 @@ const Layout = ({ children }) => {
{subItem.name} {subItem.name}
</span> </span>
<button <button
type="button"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
setSidebarOpen(false); setSidebarOpen(false);
@@ -453,6 +454,7 @@ const Layout = ({ children }) => {
> >
{sidebarCollapsed ? ( {sidebarCollapsed ? (
<button <button
type="button"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)} onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="flex items-center justify-center w-8 h-8 rounded-md hover:bg-secondary-100 transition-colors" className="flex items-center justify-center w-8 h-8 rounded-md hover:bg-secondary-100 transition-colors"
title="Expand sidebar" title="Expand sidebar"
@@ -468,6 +470,7 @@ const Layout = ({ children }) => {
</h1> </h1>
</div> </div>
<button <button
type="button"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)} onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="flex items-center justify-center w-8 h-8 rounded-md hover:bg-secondary-100 transition-colors" className="flex items-center justify-center w-8 h-8 rounded-md hover:bg-secondary-100 transition-colors"
title="Collapse sidebar" title="Collapse sidebar"
@@ -549,6 +552,7 @@ const Layout = ({ children }) => {
)} )}
{!sidebarCollapsed && ( {!sidebarCollapsed && (
<button <button
type="button"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
handleAddHost(); handleAddHost();
@@ -659,6 +663,7 @@ const Layout = ({ children }) => {
</div> </div>
</Link> </Link>
<button <button
type="button"
onClick={handleLogout} onClick={handleLogout}
className="ml-2 p-1.5 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded transition-colors" className="ml-2 p-1.5 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded transition-colors"
title="Sign out" title="Sign out"
@@ -675,6 +680,7 @@ const Layout = ({ children }) => {
Updated: {formatRelativeTimeShort(stats.lastUpdated)} Updated: {formatRelativeTimeShort(stats.lastUpdated)}
</span> </span>
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="p-1 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded flex-shrink-0 disabled:opacity-50" className="p-1 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded flex-shrink-0 disabled:opacity-50"
@@ -707,6 +713,7 @@ const Layout = ({ children }) => {
<UserCircle className="h-5 w-5" /> <UserCircle className="h-5 w-5" />
</Link> </Link>
<button <button
type="button"
onClick={handleLogout} onClick={handleLogout}
className="flex items-center justify-center w-full p-2 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-md transition-colors" className="flex items-center justify-center w-full p-2 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded-md transition-colors"
title="Sign out" title="Sign out"
@@ -717,6 +724,7 @@ const Layout = ({ children }) => {
{stats && ( {stats && (
<div className="flex flex-col items-center py-1 border-t border-secondary-200 dark:border-secondary-700"> <div className="flex flex-col items-center py-1 border-t border-secondary-200 dark:border-secondary-700">
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="p-1 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded disabled:opacity-50" className="p-1 hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded disabled:opacity-50"

View File

@@ -831,6 +831,7 @@ const Dashboard = () => {
{error.message || "Failed to load dashboard statistics"} {error.message || "Failed to load dashboard statistics"}
</p> </p>
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
className="mt-2 btn-danger text-xs" className="mt-2 btn-danger text-xs"
> >
@@ -1010,6 +1011,7 @@ const Dashboard = () => {
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button
type="button"
onClick={() => setShowSettingsModal(true)} onClick={() => setShowSettingsModal(true)}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"
title="Customize dashboard layout" title="Customize dashboard layout"
@@ -1018,6 +1020,7 @@ const Dashboard = () => {
Customize Dashboard Customize Dashboard
</button> </button>
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"

View File

@@ -163,6 +163,7 @@ const HostDetail = () => {
{error.message || "Failed to load host details"} {error.message || "Failed to load host details"}
</p> </p>
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
className="mt-2 btn-danger text-xs" className="mt-2 btn-danger text-xs"
> >
@@ -257,6 +258,7 @@ const HostDetail = () => {
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="btn-outline flex items-center gap-2 text-sm" className="btn-outline flex items-center gap-2 text-sm"
@@ -268,6 +270,7 @@ const HostDetail = () => {
{isFetching ? "Refreshing..." : "Refresh"} {isFetching ? "Refreshing..." : "Refresh"}
</button> </button>
<button <button
type="button"
onClick={() => setShowCredentialsModal(true)} onClick={() => setShowCredentialsModal(true)}
className="btn-outline flex items-center gap-2 text-sm" className="btn-outline flex items-center gap-2 text-sm"
> >
@@ -275,6 +278,7 @@ const HostDetail = () => {
Deploy Agent Deploy Agent
</button> </button>
<button <button
type="button"
onClick={() => setShowDeleteModal(true)} onClick={() => setShowDeleteModal(true)}
className="btn-danger flex items-center gap-2 text-sm" className="btn-danger flex items-center gap-2 text-sm"
> >
@@ -292,6 +296,7 @@ const HostDetail = () => {
<div className="card"> <div className="card">
<div className="flex border-b border-secondary-200 dark:border-secondary-600"> <div className="flex border-b border-secondary-200 dark:border-secondary-600">
<button <button
type="button"
onClick={() => handleTabChange("host")} onClick={() => handleTabChange("host")}
className={`px-4 py-2 text-sm font-medium ${ className={`px-4 py-2 text-sm font-medium ${
activeTab === "host" activeTab === "host"
@@ -302,6 +307,7 @@ const HostDetail = () => {
Host Info Host Info
</button> </button>
<button <button
type="button"
onClick={() => handleTabChange("network")} onClick={() => handleTabChange("network")}
className={`px-4 py-2 text-sm font-medium ${ className={`px-4 py-2 text-sm font-medium ${
activeTab === "network" activeTab === "network"
@@ -312,6 +318,7 @@ const HostDetail = () => {
Network Network
</button> </button>
<button <button
type="button"
onClick={() => handleTabChange("system")} onClick={() => handleTabChange("system")}
className={`px-4 py-2 text-sm font-medium ${ className={`px-4 py-2 text-sm font-medium ${
activeTab === "system" activeTab === "system"
@@ -322,6 +329,7 @@ const HostDetail = () => {
System System
</button> </button>
<button <button
type="button"
onClick={() => handleTabChange("monitoring")} onClick={() => handleTabChange("monitoring")}
className={`px-4 py-2 text-sm font-medium ${ className={`px-4 py-2 text-sm font-medium ${
activeTab === "monitoring" activeTab === "monitoring"
@@ -332,6 +340,7 @@ const HostDetail = () => {
Resource Resource
</button> </button>
<button <button
type="button"
onClick={() => handleTabChange("history")} onClick={() => handleTabChange("history")}
className={`px-4 py-2 text-sm font-medium ${ className={`px-4 py-2 text-sm font-medium ${
activeTab === "history" activeTab === "history"
@@ -427,6 +436,7 @@ const HostDetail = () => {
Auto-update Auto-update
</span> </span>
<button <button
type="button"
onClick={() => onClick={() =>
toggleAutoUpdateMutation.mutate(!host.auto_update) toggleAutoUpdateMutation.mutate(!host.auto_update)
} }
@@ -862,6 +872,7 @@ const HostDetail = () => {
{host.update_history.length > 5 && ( {host.update_history.length > 5 && (
<div className="px-4 py-2 border-t border-secondary-200 dark:border-secondary-600 bg-secondary-50 dark:bg-secondary-700"> <div className="px-4 py-2 border-t border-secondary-200 dark:border-secondary-600 bg-secondary-50 dark:bg-secondary-700">
<button <button
type="button"
onClick={() => setShowAllUpdates(!showAllUpdates)} onClick={() => setShowAllUpdates(!showAllUpdates)}
className="flex items-center gap-1.5 text-xs text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 font-medium" className="flex items-center gap-1.5 text-xs text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 font-medium"
> >
@@ -906,6 +917,7 @@ const HostDetail = () => {
<div className="p-4"> <div className="p-4">
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
<button <button
type="button"
onClick={() => navigate(`/packages?host=${hostId}`)} onClick={() => navigate(`/packages?host=${hostId}`)}
className="text-center p-4 bg-primary-50 dark:bg-primary-900/20 rounded-lg hover:bg-primary-100 dark:hover:bg-primary-900/30 transition-colors group" className="text-center p-4 bg-primary-50 dark:bg-primary-900/20 rounded-lg hover:bg-primary-100 dark:hover:bg-primary-900/30 transition-colors group"
title="View all packages for this host" title="View all packages for this host"
@@ -922,6 +934,7 @@ const HostDetail = () => {
</button> </button>
<button <button
type="button"
onClick={() => navigate(`/packages?host=${hostId}`)} onClick={() => navigate(`/packages?host=${hostId}`)}
className="text-center p-4 bg-warning-50 dark:bg-warning-900/20 rounded-lg hover:bg-warning-100 dark:hover:bg-warning-900/30 transition-colors group" className="text-center p-4 bg-warning-50 dark:bg-warning-900/20 rounded-lg hover:bg-warning-100 dark:hover:bg-warning-900/30 transition-colors group"
title="View outdated packages for this host" title="View outdated packages for this host"
@@ -938,6 +951,7 @@ const HostDetail = () => {
</button> </button>
<button <button
type="button"
onClick={() => onClick={() =>
navigate(`/packages?host=${hostId}&filter=security`) navigate(`/packages?host=${hostId}&filter=security`)
} }
@@ -1083,6 +1097,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
Host Setup - {host.friendly_name} Host Setup - {host.friendly_name}
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >
@@ -1094,6 +1109,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
<div className="border-b border-secondary-200 dark:border-secondary-600 mb-6"> <div className="border-b border-secondary-200 dark:border-secondary-600 mb-6">
<nav className="-mb-px flex space-x-8"> <nav className="-mb-px flex space-x-8">
<button <button
type="button"
onClick={() => setActiveTab("quick-install")} onClick={() => setActiveTab("quick-install")}
className={`py-2 px-1 border-b-2 font-medium text-sm ${ className={`py-2 px-1 border-b-2 font-medium text-sm ${
activeTab === "quick-install" activeTab === "quick-install"
@@ -1104,6 +1120,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
Quick Install Quick Install
</button> </button>
<button <button
type="button"
onClick={() => setActiveTab("credentials")} onClick={() => setActiveTab("credentials")}
className={`py-2 px-1 border-b-2 font-medium text-sm ${ className={`py-2 px-1 border-b-2 font-medium text-sm ${
activeTab === "credentials" activeTab === "credentials"
@@ -1135,6 +1152,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-primary-300 dark:border-primary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-primary-300 dark:border-primary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
`curl -s ${serverUrl}/api/v1/hosts/install | bash -s -- ${serverUrl} "${host.api_id}" "${host.api_key}"`, `curl -s ${serverUrl}/api/v1/hosts/install | bash -s -- ${serverUrl} "${host.api_id}" "${host.api_key}"`,
@@ -1168,6 +1186,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
`curl -o /tmp/patchmon-agent.sh ${serverUrl}/api/v1/hosts/agent/download`, `curl -o /tmp/patchmon-agent.sh ${serverUrl}/api/v1/hosts/agent/download`,
@@ -1193,6 +1212,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
"sudo mkdir -p /etc/patchmon && sudo mv /tmp/patchmon-agent.sh /usr/local/bin/patchmon-agent.sh && sudo chmod +x /usr/local/bin/patchmon-agent.sh", "sudo mkdir -p /etc/patchmon && sudo mv /tmp/patchmon-agent.sh /usr/local/bin/patchmon-agent.sh && sudo chmod +x /usr/local/bin/patchmon-agent.sh",
@@ -1218,6 +1238,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
`sudo /usr/local/bin/patchmon-agent.sh configure "${host.api_id}" "${host.api_key}"`, `sudo /usr/local/bin/patchmon-agent.sh configure "${host.api_id}" "${host.api_key}"`,
@@ -1243,6 +1264,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
"sudo /usr/local/bin/patchmon-agent.sh test", "sudo /usr/local/bin/patchmon-agent.sh test",
@@ -1268,6 +1290,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
"sudo /usr/local/bin/patchmon-agent.sh update", "sudo /usr/local/bin/patchmon-agent.sh update",
@@ -1293,6 +1316,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-white dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
`echo "${new Date().getMinutes()} * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1" | sudo crontab -`, `echo "${new Date().getMinutes()} * * * * /usr/local/bin/patchmon-agent.sh update >/dev/null 2>&1" | sudo crontab -`,
@@ -1329,6 +1353,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-secondary-50 dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-secondary-50 dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => copyToClipboard(host.api_id)} onClick={() => copyToClipboard(host.api_id)}
className="btn-outline flex items-center gap-1" className="btn-outline flex items-center gap-1"
> >
@@ -1350,6 +1375,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-secondary-50 dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white" className="flex-1 px-3 py-2 border border-secondary-300 dark:border-secondary-600 rounded-md bg-secondary-50 dark:bg-secondary-800 text-sm font-mono text-secondary-900 dark:text-white"
/> />
<button <button
type="button"
onClick={() => setShowApiKey(!showApiKey)} onClick={() => setShowApiKey(!showApiKey)}
className="btn-outline flex items-center gap-1" className="btn-outline flex items-center gap-1"
> >
@@ -1360,6 +1386,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
)} )}
</button> </button>
<button <button
type="button"
onClick={() => copyToClipboard(host.api_key)} onClick={() => copyToClipboard(host.api_key)}
className="btn-outline flex items-center gap-1" className="btn-outline flex items-center gap-1"
> >
@@ -1389,7 +1416,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
)} )}
<div className="flex justify-end pt-6"> <div className="flex justify-end pt-6">
<button onClick={onClose} className="btn-primary"> <button type="button" onClick={onClose} className="btn-primary">
Close Close
</button> </button>
</div> </div>
@@ -1441,6 +1468,7 @@ const DeleteConfirmationModal = ({
<div className="flex justify-end gap-3"> <div className="flex justify-end gap-3">
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="btn-outline" className="btn-outline"
disabled={isLoading} disabled={isLoading}
@@ -1448,6 +1476,7 @@ const DeleteConfirmationModal = ({
Cancel Cancel
</button> </button>
<button <button
type="button"
onClick={onConfirm} onClick={onConfirm}
className="btn-danger" className="btn-danger"
disabled={isLoading} disabled={isLoading}

View File

@@ -126,6 +126,7 @@ const HostGroups = () => {
</p> </p>
</div> </div>
<button <button
type="button"
onClick={() => setShowCreateModal(true)} onClick={() => setShowCreateModal(true)}
className="btn-primary flex items-center gap-2" className="btn-primary flex items-center gap-2"
> >
@@ -161,6 +162,7 @@ const HostGroups = () => {
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
type="button"
onClick={() => handleEdit(group)} onClick={() => handleEdit(group)}
className="p-1 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded" className="p-1 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded"
title="Edit group" title="Edit group"
@@ -168,6 +170,7 @@ const HostGroups = () => {
<Edit className="h-4 w-4" /> <Edit className="h-4 w-4" />
</button> </button>
<button <button
type="button"
onClick={() => handleDeleteClick(group)} onClick={() => handleDeleteClick(group)}
className="p-1 text-secondary-400 hover:text-danger-600 hover:bg-danger-50 rounded" className="p-1 text-secondary-400 hover:text-danger-600 hover:bg-danger-50 rounded"
title="Delete group" title="Delete group"
@@ -199,6 +202,7 @@ const HostGroups = () => {
Create your first host group to organize your hosts Create your first host group to organize your hosts
</p> </p>
<button <button
type="button"
onClick={() => setShowCreateModal(true)} onClick={() => setShowCreateModal(true)}
className="btn-primary flex items-center gap-2 mx-auto" className="btn-primary flex items-center gap-2 mx-auto"
> >
@@ -479,6 +483,7 @@ const DeleteHostGroupModal = ({ group, onClose, onConfirm, isLoading }) => {
<div className="flex justify-end gap-3"> <div className="flex justify-end gap-3">
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="btn-outline" className="btn-outline"
disabled={isLoading} disabled={isLoading}
@@ -486,6 +491,7 @@ const DeleteHostGroupModal = ({ group, onClose, onConfirm, isLoading }) => {
Cancel Cancel
</button> </button>
<button <button
type="button"
onClick={onConfirm} onClick={onConfirm}
className="btn-danger" className="btn-danger"
disabled={isLoading || group._count.hosts > 0} disabled={isLoading || group._count.hosts > 0}

View File

@@ -103,6 +103,7 @@ const AddHostModal = ({ isOpen, onClose, onSuccess }) => {
Add New Host Add New Host
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >
@@ -369,6 +370,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
Host Setup - {host.friendly_name} Host Setup - {host.friendly_name}
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600" className="text-secondary-400 hover:text-secondary-600"
> >
@@ -379,6 +381,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
{/* Tabs */} {/* Tabs */}
<div className="flex space-x-1 mb-6 bg-secondary-100 p-1 rounded-lg"> <div className="flex space-x-1 mb-6 bg-secondary-100 p-1 rounded-lg">
<button <button
type="button"
onClick={() => setActiveTab("quick")} onClick={() => setActiveTab("quick")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${ className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
activeTab === "quick" activeTab === "quick"
@@ -389,6 +392,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
Quick Install Quick Install
</button> </button>
<button <button
type="button"
onClick={() => setActiveTab("credentials")} onClick={() => setActiveTab("credentials")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${ className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
activeTab === "credentials" activeTab === "credentials"
@@ -399,6 +403,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
API Credentials API Credentials
</button> </button>
<button <button
type="button"
onClick={() => setActiveTab("setup")} onClick={() => setActiveTab("setup")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${ className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
activeTab === "setup" activeTab === "setup"
@@ -409,6 +414,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
Setup Instructions Setup Instructions
</button> </button>
<button <button
type="button"
onClick={() => setActiveTab("script")} onClick={() => setActiveTab("script")}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${ className={`px-4 py-2 rounded-md text-sm font-medium transition-colors ${
activeTab === "script" activeTab === "script"
@@ -444,6 +450,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
{commands.oneLine} {commands.oneLine}
</code> </code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(commands.oneLine, "Installation command") copyToClipboard(commands.oneLine, "Installation command")
} }
@@ -512,6 +519,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
className="flex-1 block w-full border-secondary-300 rounded-l-md shadow-sm bg-secondary-50" className="flex-1 block w-full border-secondary-300 rounded-l-md shadow-sm bg-secondary-50"
/> />
<button <button
type="button"
onClick={() => copyToClipboard(host.apiId, "API ID")} onClick={() => copyToClipboard(host.apiId, "API ID")}
className="px-3 py-2 border border-l-0 border-secondary-300 rounded-r-md bg-secondary-50 hover:bg-secondary-100" className="px-3 py-2 border border-l-0 border-secondary-300 rounded-r-md bg-secondary-50 hover:bg-secondary-100"
> >
@@ -532,6 +540,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
className="flex-1 block w-full border-secondary-300 rounded-l-md shadow-sm bg-secondary-50" className="flex-1 block w-full border-secondary-300 rounded-l-md shadow-sm bg-secondary-50"
/> />
<button <button
type="button"
onClick={() => setShowApiKey(!showApiKey)} onClick={() => setShowApiKey(!showApiKey)}
className="px-3 py-2 border border-l-0 border-r-0 border-secondary-300 bg-secondary-50 hover:bg-secondary-100" className="px-3 py-2 border border-l-0 border-r-0 border-secondary-300 bg-secondary-50 hover:bg-secondary-100"
> >
@@ -542,6 +551,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
)} )}
</button> </button>
<button <button
type="button"
onClick={() => copyToClipboard(host.apiKey, "API Key")} onClick={() => copyToClipboard(host.apiKey, "API Key")}
className="px-3 py-2 border border-l-0 border-secondary-300 rounded-r-md bg-secondary-50 hover:bg-secondary-100" className="px-3 py-2 border border-l-0 border-secondary-300 rounded-r-md bg-secondary-50 hover:bg-secondary-100"
> >
@@ -586,6 +596,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
{commands.download} {commands.download}
</code> </code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(commands.download, "Download commands") copyToClipboard(commands.download, "Download commands")
} }
@@ -606,6 +617,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<code className="flex-1">{commands.configure}</code> <code className="flex-1">{commands.configure}</code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(commands.configure, "Configure command") copyToClipboard(commands.configure, "Configure command")
} }
@@ -626,6 +638,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<code className="flex-1">{commands.test}</code> <code className="flex-1">{commands.test}</code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(commands.test, "Test command") copyToClipboard(commands.test, "Test command")
} }
@@ -650,6 +663,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<code className="flex-1">{commands.initialUpdate}</code> <code className="flex-1">{commands.initialUpdate}</code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard( copyToClipboard(
commands.initialUpdate, commands.initialUpdate,
@@ -673,6 +687,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<code className="flex-1">{commands.crontab}</code> <code className="flex-1">{commands.crontab}</code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(commands.crontab, "Crontab command") copyToClipboard(commands.crontab, "Crontab command")
} }
@@ -709,6 +724,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
Complete Setup Script Complete Setup Script
</h5> </h5>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(commands.fullSetup, "Complete setup script") copyToClipboard(commands.fullSetup, "Complete setup script")
} }
@@ -750,6 +766,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`,
Download Agent Script Download Agent Script
</a> </a>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="px-4 py-2 text-sm font-medium text-secondary-700 bg-white border border-secondary-300 rounded-md hover:bg-secondary-50" className="px-4 py-2 text-sm font-medium text-secondary-700 bg-white border border-secondary-300 rounded-md hover:bg-secondary-50"
> >
@@ -1270,6 +1287,7 @@ const Hosts = () => {
case "select": case "select":
return ( return (
<button <button
type="button"
onClick={() => handleSelectHost(host.id)} onClick={() => handleSelectHost(host.id)}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1373,6 +1391,7 @@ const Hosts = () => {
case "updates": case "updates":
return ( return (
<button <button
type="button"
onClick={() => navigate(`/packages?host=${host.id}`)} onClick={() => navigate(`/packages?host=${host.id}`)}
className="text-sm text-primary-600 hover:text-primary-900 dark:text-primary-400 dark:hover:text-primary-300 font-medium hover:underline" className="text-sm text-primary-600 hover:text-primary-900 dark:text-primary-400 dark:hover:text-primary-300 font-medium hover:underline"
title="View packages for this host" title="View packages for this host"
@@ -1472,6 +1491,7 @@ const Hosts = () => {
{error.message || "Failed to load hosts"} {error.message || "Failed to load hosts"}
</p> </p>
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
className="mt-2 btn-danger text-xs" className="mt-2 btn-danger text-xs"
> >
@@ -1515,6 +1535,7 @@ const Hosts = () => {
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"
@@ -1526,6 +1547,7 @@ const Hosts = () => {
{isFetching ? "Refreshing..." : "Refresh"} {isFetching ? "Refreshing..." : "Refresh"}
</button> </button>
<button <button
type="button"
onClick={() => setShowAddModal(true)} onClick={() => setShowAddModal(true)}
className="btn-primary flex items-center gap-2" className="btn-primary flex items-center gap-2"
> >
@@ -1615,6 +1637,7 @@ const Hosts = () => {
{selectedHosts.length !== 1 ? "s" : ""} selected {selectedHosts.length !== 1 ? "s" : ""} selected
</span> </span>
<button <button
type="button"
onClick={() => setShowBulkAssignModal(true)} onClick={() => setShowBulkAssignModal(true)}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"
> >
@@ -1622,6 +1645,7 @@ const Hosts = () => {
Assign to Group Assign to Group
</button> </button>
<button <button
type="button"
onClick={() => setShowBulkDeleteModal(true)} onClick={() => setShowBulkDeleteModal(true)}
className="btn-danger flex items-center gap-2" className="btn-danger flex items-center gap-2"
> >
@@ -1629,6 +1653,7 @@ const Hosts = () => {
Delete Delete
</button> </button>
<button <button
type="button"
onClick={() => setSelectedHosts([])} onClick={() => setSelectedHosts([])}
className="text-sm text-secondary-500 hover:text-secondary-700" className="text-sm text-secondary-500 hover:text-secondary-700"
> >
@@ -1656,6 +1681,7 @@ const Hosts = () => {
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
<button <button
type="button"
onClick={() => setShowFilters(!showFilters)} onClick={() => setShowFilters(!showFilters)}
className={`btn-outline flex items-center gap-2 ${showFilters ? "bg-primary-50 border-primary-300" : ""}`} className={`btn-outline flex items-center gap-2 ${showFilters ? "bg-primary-50 border-primary-300" : ""}`}
> >
@@ -1663,6 +1689,7 @@ const Hosts = () => {
Filters Filters
</button> </button>
<button <button
type="button"
onClick={() => setShowColumnSettings(true)} onClick={() => setShowColumnSettings(true)}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"
> >
@@ -1683,6 +1710,7 @@ const Hosts = () => {
<ChevronDown className="absolute right-1 top-1/2 transform -translate-y-1/2 h-4 w-4 text-secondary-400 dark:text-secondary-500 pointer-events-none" /> <ChevronDown className="absolute right-1 top-1/2 transform -translate-y-1/2 h-4 w-4 text-secondary-400 dark:text-secondary-500 pointer-events-none" />
</div> </div>
<button <button
type="button"
onClick={() => setHideStale(!hideStale)} onClick={() => setHideStale(!hideStale)}
className={`btn-outline flex items-center gap-2 ${hideStale ? "bg-primary-50 border-primary-300" : ""}`} className={`btn-outline flex items-center gap-2 ${hideStale ? "bg-primary-50 border-primary-300" : ""}`}
> >
@@ -1690,6 +1718,7 @@ const Hosts = () => {
Hide Stale Hide Stale
</button> </button>
<button <button
type="button"
onClick={() => setShowAddModal(true)} onClick={() => setShowAddModal(true)}
className="btn-primary flex items-center gap-2" className="btn-primary flex items-center gap-2"
> >
@@ -1754,6 +1783,7 @@ const Hosts = () => {
</div> </div>
<div className="flex items-end"> <div className="flex items-end">
<button <button
type="button"
onClick={() => { onClick={() => {
setSearchTerm(""); setSearchTerm("");
setGroupFilter("all"); setGroupFilter("all");
@@ -1819,6 +1849,7 @@ const Hosts = () => {
> >
{column.id === "select" ? ( {column.id === "select" ? (
<button <button
type="button"
onClick={handleSelectAll} onClick={handleSelectAll}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1831,6 +1862,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "host" ? ( ) : column.id === "host" ? (
<button <button
type="button"
onClick={() => onClick={() =>
handleSort("friendlyName") handleSort("friendlyName")
} }
@@ -1841,6 +1873,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "hostname" ? ( ) : column.id === "hostname" ? (
<button <button
type="button"
onClick={() => handleSort("hostname")} onClick={() => handleSort("hostname")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1849,6 +1882,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "ip" ? ( ) : column.id === "ip" ? (
<button <button
type="button"
onClick={() => handleSort("ip")} onClick={() => handleSort("ip")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1857,6 +1891,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "group" ? ( ) : column.id === "group" ? (
<button <button
type="button"
onClick={() => handleSort("group")} onClick={() => handleSort("group")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1865,6 +1900,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "os" ? ( ) : column.id === "os" ? (
<button <button
type="button"
onClick={() => handleSort("os")} onClick={() => handleSort("os")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1873,6 +1909,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "os_version" ? ( ) : column.id === "os_version" ? (
<button <button
type="button"
onClick={() => handleSort("os_version")} onClick={() => handleSort("os_version")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1881,6 +1918,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "agent_version" ? ( ) : column.id === "agent_version" ? (
<button <button
type="button"
onClick={() => onClick={() =>
handleSort("agent_version") handleSort("agent_version")
} }
@@ -1895,6 +1933,7 @@ const Hosts = () => {
</div> </div>
) : column.id === "status" ? ( ) : column.id === "status" ? (
<button <button
type="button"
onClick={() => handleSort("status")} onClick={() => handleSort("status")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1903,6 +1942,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "updates" ? ( ) : column.id === "updates" ? (
<button <button
type="button"
onClick={() => handleSort("updates")} onClick={() => handleSort("updates")}
className="flex items-center gap-2 hover:text-secondary-700" className="flex items-center gap-2 hover:text-secondary-700"
> >
@@ -1911,6 +1951,7 @@ const Hosts = () => {
</button> </button>
) : column.id === "last_update" ? ( ) : column.id === "last_update" ? (
<button <button
type="button"
onClick={() => onClick={() =>
handleSort("last_update") handleSort("last_update")
} }
@@ -2047,6 +2088,7 @@ const BulkAssignModal = ({
Assign to Host Group Assign to Host Group
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600" className="text-secondary-400 hover:text-secondary-600"
> >
@@ -2135,6 +2177,7 @@ const BulkDeleteModal = ({
Delete Hosts Delete Hosts
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
disabled={isLoading} disabled={isLoading}
@@ -2236,6 +2279,7 @@ const ColumnSettingsModal = ({
Column Settings Column Settings
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >
@@ -2270,6 +2314,7 @@ const ColumnSettingsModal = ({
</span> </span>
</div> </div>
<button <button
type="button"
onClick={() => onToggleVisibility(column.id)} onClick={() => onToggleVisibility(column.id)}
className={`p-1 rounded ${ className={`p-1 rounded ${
column.visible column.visible
@@ -2288,10 +2333,10 @@ const ColumnSettingsModal = ({
</div> </div>
<div className="flex justify-between mt-6"> <div className="flex justify-between mt-6">
<button onClick={onReset} className="btn-outline"> <button type="button" onClick={onReset} className="btn-outline">
Reset to Default Reset to Default
</button> </button>
<button onClick={onClose} className="btn-primary"> <button type="button" onClick={onClose} className="btn-primary">
Done Done
</button> </button>
</div> </div>

View File

@@ -143,6 +143,7 @@ const Options = () => {
</p> </p>
</div> </div>
<button <button
type="button"
onClick={() => setShowCreateModal(true)} onClick={() => setShowCreateModal(true)}
className="btn-primary flex items-center gap-2" className="btn-primary flex items-center gap-2"
> >
@@ -178,6 +179,7 @@ const Options = () => {
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
type="button"
onClick={() => handleEdit(group)} onClick={() => handleEdit(group)}
className="p-1 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded" className="p-1 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded"
title="Edit group" title="Edit group"
@@ -185,6 +187,7 @@ const Options = () => {
<Edit className="h-4 w-4" /> <Edit className="h-4 w-4" />
</button> </button>
<button <button
type="button"
onClick={() => handleDeleteClick(group)} onClick={() => handleDeleteClick(group)}
className="p-1 text-secondary-400 hover:text-danger-600 hover:bg-danger-50 rounded" className="p-1 text-secondary-400 hover:text-danger-600 hover:bg-danger-50 rounded"
title="Delete group" title="Delete group"
@@ -216,6 +219,7 @@ const Options = () => {
Create your first host group to organize your hosts Create your first host group to organize your hosts
</p> </p>
<button <button
type="button"
onClick={() => setShowCreateModal(true)} onClick={() => setShowCreateModal(true)}
className="btn-primary flex items-center gap-2 mx-auto" className="btn-primary flex items-center gap-2 mx-auto"
> >
@@ -260,6 +264,7 @@ const Options = () => {
const Icon = tab.icon; const Icon = tab.icon;
return ( return (
<button <button
type="button"
key={tab.id} key={tab.id}
onClick={() => setActiveTab(tab.id)} onClick={() => setActiveTab(tab.id)}
className={`py-2 px-1 border-b-2 font-medium text-sm flex items-center gap-2 ${ className={`py-2 px-1 border-b-2 font-medium text-sm flex items-center gap-2 ${
@@ -558,6 +563,7 @@ const DeleteHostGroupModal = ({ group, onClose, onConfirm, isLoading }) => {
<div className="flex justify-end gap-3"> <div className="flex justify-end gap-3">
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="btn-outline" className="btn-outline"
disabled={isLoading} disabled={isLoading}
@@ -565,6 +571,7 @@ const DeleteHostGroupModal = ({ group, onClose, onConfirm, isLoading }) => {
Cancel Cancel
</button> </button>
<button <button
type="button"
onClick={onConfirm} onClick={onConfirm}
className="btn-danger" className="btn-danger"
disabled={isLoading || group._count.hosts > 0} disabled={isLoading || group._count.hosts > 0}

View File

@@ -272,6 +272,7 @@ const Packages = () => {
pkg.affectedHostsCount || pkg.affectedHosts?.length || 0; pkg.affectedHostsCount || pkg.affectedHosts?.length || 0;
return ( return (
<button <button
type="button"
onClick={() => handleAffectedHostsClick(pkg)} onClick={() => handleAffectedHostsClick(pkg)}
className="text-left hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded p-1 -m-1 transition-colors group" className="text-left hover:bg-secondary-100 dark:hover:bg-secondary-700 rounded p-1 -m-1 transition-colors group"
title={`Click to view all ${affectedHostsCount} affected hosts`} title={`Click to view all ${affectedHostsCount} affected hosts`}
@@ -354,6 +355,7 @@ const Packages = () => {
{error.message || "Failed to load packages"} {error.message || "Failed to load packages"}
</p> </p>
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
className="mt-2 btn-danger text-xs" className="mt-2 btn-danger text-xs"
> >
@@ -380,6 +382,7 @@ const Packages = () => {
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"
@@ -524,6 +527,7 @@ const Packages = () => {
{/* Columns Button */} {/* Columns Button */}
<div className="flex items-center"> <div className="flex items-center">
<button <button
type="button"
onClick={() => setShowColumnSettings(true)} onClick={() => setShowColumnSettings(true)}
className="flex items-center gap-2 px-3 py-2 text-sm text-secondary-700 dark:text-secondary-300 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600 transition-colors" className="flex items-center gap-2 px-3 py-2 text-sm text-secondary-700 dark:text-secondary-300 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600 transition-colors"
> >
@@ -560,6 +564,7 @@ const Packages = () => {
className="px-4 py-2 text-center text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider" className="px-4 py-2 text-center text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider"
> >
<button <button
type="button"
onClick={() => handleSort(column.id)} onClick={() => handleSort(column.id)}
className="flex items-center gap-1 hover:text-secondary-700 dark:hover:text-secondary-200 transition-colors" className="flex items-center gap-1 hover:text-secondary-700 dark:hover:text-secondary-200 transition-colors"
> >
@@ -644,6 +649,7 @@ const ColumnSettingsModal = ({
Customize Columns Customize Columns
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >
@@ -672,6 +678,7 @@ const ColumnSettingsModal = ({
</span> </span>
</div> </div>
<button <button
type="button"
onClick={() => onToggleVisibility(column.id)} onClick={() => onToggleVisibility(column.id)}
className={`p-1 rounded ${ className={`p-1 rounded ${
column.visible column.visible
@@ -691,12 +698,14 @@ const ColumnSettingsModal = ({
<div className="flex justify-between mt-6"> <div className="flex justify-between mt-6">
<button <button
type="button"
onClick={onReset} onClick={onReset}
className="px-4 py-2 text-sm font-medium text-secondary-700 dark:text-secondary-200 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600" className="px-4 py-2 text-sm font-medium text-secondary-700 dark:text-secondary-200 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600"
> >
Reset to Default Reset to Default
</button> </button>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="px-4 py-2 text-sm font-medium text-white bg-primary-600 rounded-md hover:bg-primary-700" className="px-4 py-2 text-sm font-medium text-white bg-primary-600 rounded-md hover:bg-primary-700"
> >

View File

@@ -108,6 +108,7 @@ const Permissions = () => {
<div className="flex justify-end items-center"> <div className="flex justify-end items-center">
<div className="flex space-x-3"> <div className="flex space-x-3">
<button <button
type="button"
onClick={() => refreshPermissions()} onClick={() => refreshPermissions()}
className="inline-flex items-center px-4 py-2 border border-secondary-300 text-sm font-medium rounded-md text-secondary-700 bg-white hover:bg-secondary-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500" className="inline-flex items-center px-4 py-2 border border-secondary-300 text-sm font-medium rounded-md text-secondary-700 bg-white hover:bg-secondary-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
> >
@@ -115,6 +116,7 @@ const Permissions = () => {
Refresh Permissions Refresh Permissions
</button> </button>
<button <button
type="button"
onClick={() => setShowAddModal(true)} onClick={() => setShowAddModal(true)}
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500" className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
> >
@@ -265,6 +267,7 @@ const RolePermissionsCard = ({
{isEditing ? ( {isEditing ? (
<> <>
<button <button
type="button"
onClick={handleSave} onClick={handleSave}
className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700" className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700"
> >
@@ -272,6 +275,7 @@ const RolePermissionsCard = ({
Save Save
</button> </button>
<button <button
type="button"
onClick={onCancel} onClick={onCancel}
className="inline-flex items-center px-3 py-1 border border-secondary-300 dark:border-secondary-600 text-sm font-medium rounded-md text-secondary-700 dark:text-secondary-200 bg-white dark:bg-secondary-700 hover:bg-secondary-50 dark:hover:bg-secondary-600" className="inline-flex items-center px-3 py-1 border border-secondary-300 dark:border-secondary-600 text-sm font-medium rounded-md text-secondary-700 dark:text-secondary-200 bg-white dark:bg-secondary-700 hover:bg-secondary-50 dark:hover:bg-secondary-600"
> >
@@ -282,6 +286,7 @@ const RolePermissionsCard = ({
) : ( ) : (
<> <>
<button <button
type="button"
onClick={onEdit} onClick={onEdit}
disabled={isBuiltInRole} disabled={isBuiltInRole}
className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed" className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed"
@@ -291,6 +296,7 @@ const RolePermissionsCard = ({
</button> </button>
{!isBuiltInRole && ( {!isBuiltInRole && (
<button <button
type="button"
onClick={() => onDelete(role.role)} onClick={() => onDelete(role.role)}
className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700" className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700"
> >

View File

@@ -192,6 +192,7 @@ const Profile = () => {
const Icon = tab.icon; const Icon = tab.icon;
return ( return (
<button <button
type="button"
key={tab.id} key={tab.id}
onClick={() => setActiveTab(tab.id)} onClick={() => setActiveTab(tab.id)}
className={`py-4 px-1 border-b-2 font-medium text-sm flex items-center ${ className={`py-4 px-1 border-b-2 font-medium text-sm flex items-center ${
@@ -505,6 +506,7 @@ const Profile = () => {
</div> </div>
</div> </div>
<button <button
type="button"
onClick={toggleTheme} onClick={toggleTheme}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 ${ className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 ${
isDark ? "bg-primary-600" : "bg-secondary-300" isDark ? "bg-primary-600" : "bg-secondary-300"
@@ -797,6 +799,7 @@ const TfaTab = () => {
<div> <div>
{tfaStatus?.enabled ? ( {tfaStatus?.enabled ? (
<button <button
type="button"
onClick={() => setSetupStep("disable")} onClick={() => setSetupStep("disable")}
className="btn-outline text-danger-600 border-danger-300 hover:bg-danger-50" className="btn-outline text-danger-600 border-danger-300 hover:bg-danger-50"
> >
@@ -805,6 +808,7 @@ const TfaTab = () => {
</button> </button>
) : ( ) : (
<button <button
type="button"
onClick={handleSetup} onClick={handleSetup}
disabled={setupMutation.isPending} disabled={setupMutation.isPending}
className="btn-primary" className="btn-primary"
@@ -827,6 +831,7 @@ const TfaTab = () => {
authenticator device. authenticator device.
</p> </p>
<button <button
type="button"
onClick={handleRegenerateBackupCodes} onClick={handleRegenerateBackupCodes}
disabled={regenerateBackupCodesMutation.isPending} disabled={regenerateBackupCodesMutation.isPending}
className="btn-outline" className="btn-outline"
@@ -871,6 +876,7 @@ const TfaTab = () => {
{setupMutation.data.manualEntryKey} {setupMutation.data.manualEntryKey}
</code> </code>
<button <button
type="button"
onClick={() => onClick={() =>
copyToClipboard(setupMutation.data.manualEntryKey) copyToClipboard(setupMutation.data.manualEntryKey)
} }
@@ -884,6 +890,7 @@ const TfaTab = () => {
<div className="text-center"> <div className="text-center">
<button <button
type="button"
onClick={() => setSetupStep("verify")} onClick={() => setSetupStep("verify")}
className="btn-primary" className="btn-primary"
> >
@@ -979,11 +986,12 @@ const TfaTab = () => {
</div> </div>
</div> </div>
<div className="flex space-x-3"> <div className="flex space-x-3">
<button onClick={downloadBackupCodes} className="btn-outline"> <button type="button" onClick={downloadBackupCodes} className="btn-outline">
<Download className="h-4 w-4 mr-2" /> <Download className="h-4 w-4 mr-2" />
Download Codes Download Codes
</button> </button>
<button <button
type="button"
onClick={() => { onClick={() => {
setSetupStep("status"); setSetupStep("status");
queryClient.invalidateQueries(["tfaStatus"]); queryClient.invalidateQueries(["tfaStatus"]);

View File

@@ -238,6 +238,7 @@ const Repositories = () => {
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button
type="button"
onClick={() => refetch()} onClick={() => refetch()}
disabled={isFetching} disabled={isFetching}
className="btn-outline flex items-center gap-2" className="btn-outline flex items-center gap-2"
@@ -363,6 +364,7 @@ const Repositories = () => {
{/* Columns Button */} {/* Columns Button */}
<div className="flex items-center"> <div className="flex items-center">
<button <button
type="button"
onClick={() => setShowColumnSettings(true)} onClick={() => setShowColumnSettings(true)}
className="flex items-center gap-2 px-3 py-2 text-sm text-secondary-700 dark:text-secondary-300 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600 transition-colors" className="flex items-center gap-2 px-3 py-2 text-sm text-secondary-700 dark:text-secondary-300 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600 transition-colors"
> >
@@ -399,6 +401,7 @@ const Repositories = () => {
className="px-4 py-2 text-center text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider" className="px-4 py-2 text-center text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider"
> >
<button <button
type="button"
onClick={() => handleSort(column.id)} onClick={() => handleSort(column.id)}
className="flex items-center gap-1 hover:text-secondary-700 dark:hover:text-secondary-200 transition-colors" className="flex items-center gap-1 hover:text-secondary-700 dark:hover:text-secondary-200 transition-colors"
> >
@@ -567,6 +570,7 @@ const ColumnSettingsModal = ({
Column Settings Column Settings
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >
@@ -591,6 +595,7 @@ const ColumnSettingsModal = ({
</span> </span>
</div> </div>
<button <button
type="button"
onClick={() => onToggleVisibility(column.id)} onClick={() => onToggleVisibility(column.id)}
className={`w-4 h-4 rounded border-2 flex items-center justify-center ${ className={`w-4 h-4 rounded border-2 flex items-center justify-center ${
column.visible column.visible
@@ -606,12 +611,14 @@ const ColumnSettingsModal = ({
<div className="flex justify-between mt-6"> <div className="flex justify-between mt-6">
<button <button
type="button"
onClick={onReset} onClick={onReset}
className="px-4 py-2 text-sm text-secondary-600 dark:text-secondary-400 hover:text-secondary-800 dark:hover:text-secondary-200" className="px-4 py-2 text-sm text-secondary-600 dark:text-secondary-400 hover:text-secondary-800 dark:hover:text-secondary-200"
> >
Reset to Default Reset to Default
</button> </button>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="px-4 py-2 bg-primary-600 text-white text-sm rounded-md hover:bg-primary-700 transition-colors" className="px-4 py-2 bg-primary-600 text-white text-sm rounded-md hover:bg-primary-700 transition-colors"
> >

View File

@@ -161,6 +161,7 @@ const RepositoryDetail = () => {
{editMode ? ( {editMode ? (
<> <>
<button <button
type="button"
onClick={handleCancel} onClick={handleCancel}
className="btn-outline" className="btn-outline"
disabled={updateRepositoryMutation.isPending} disabled={updateRepositoryMutation.isPending}
@@ -168,6 +169,7 @@ const RepositoryDetail = () => {
Cancel Cancel
</button> </button>
<button <button
type="button"
onClick={handleSave} onClick={handleSave}
className="btn-primary" className="btn-primary"
disabled={updateRepositoryMutation.isPending} disabled={updateRepositoryMutation.isPending}
@@ -178,7 +180,7 @@ const RepositoryDetail = () => {
</button> </button>
</> </>
) : ( ) : (
<button onClick={handleEdit} className="btn-primary"> <button type="button" onClick={handleEdit} className="btn-primary">
Edit Repository Edit Repository
</button> </button>
)} )}

View File

@@ -431,6 +431,7 @@ const Settings = () => {
const Icon = tab.icon; const Icon = tab.icon;
return ( return (
<button <button
type="button"
key={tab.id} key={tab.id}
onClick={() => setActiveTab(tab.id)} onClick={() => setActiveTab(tab.id)}
className={`py-4 px-1 border-b-2 font-medium text-sm flex items-center gap-2 ${ className={`py-4 px-1 border-b-2 font-medium text-sm flex items-center gap-2 ${
@@ -792,6 +793,7 @@ const Settings = () => {
</p> </p>
</div> </div>
<button <button
type="button"
onClick={() => setShowAgentVersionModal(true)} onClick={() => setShowAgentVersionModal(true)}
className="btn-primary flex items-center gap-2" className="btn-primary flex items-center gap-2"
> >
@@ -888,6 +890,7 @@ const Settings = () => {
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
type="button"
onClick={() => { onClick={() => {
const downloadUrl = `/api/v1/hosts/agent/download?version=${version.version}`; const downloadUrl = `/api/v1/hosts/agent/download?version=${version.version}`;
window.open(downloadUrl, "_blank"); window.open(downloadUrl, "_blank");
@@ -898,6 +901,7 @@ const Settings = () => {
Download Download
</button> </button>
<button <button
type="button"
onClick={() => onClick={() =>
setCurrentAgentVersionMutation.mutate(version.id) setCurrentAgentVersionMutation.mutate(version.id)
} }
@@ -911,6 +915,7 @@ const Settings = () => {
Set Current Set Current
</button> </button>
<button <button
type="button"
onClick={() => onClick={() =>
setDefaultAgentVersionMutation.mutate(version.id) setDefaultAgentVersionMutation.mutate(version.id)
} }
@@ -924,6 +929,7 @@ const Settings = () => {
Set Default Set Default
</button> </button>
<button <button
type="button"
onClick={() => onClick={() =>
deleteAgentVersionMutation.mutate(version.id) deleteAgentVersionMutation.mutate(version.id)
} }
@@ -1208,6 +1214,7 @@ const Settings = () => {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<button <button
type="button"
onClick={checkForUpdates} onClick={checkForUpdates}
disabled={versionInfo.checking} disabled={versionInfo.checking}
className="btn-primary flex items-center gap-2" className="btn-primary flex items-center gap-2"
@@ -1360,6 +1367,7 @@ const AgentVersionModal = ({ isOpen, onClose, onSubmit, isLoading }) => {
Add Agent Version Add Agent Version
</h3> </h3>
<button <button
type="button"
onClick={onClose} onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
> >

View File

@@ -121,6 +121,7 @@ const Users = () => {
{/* Header */} {/* Header */}
<div className="flex justify-end items-center"> <div className="flex justify-end items-center">
<button <button
type="button"
onClick={() => setShowAddModal(true)} onClick={() => setShowAddModal(true)}
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500" className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
> >
@@ -193,6 +194,7 @@ const Users = () => {
</div> </div>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<button <button
type="button"
onClick={() => handleEditUser(user)} onClick={() => handleEditUser(user)}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300" className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
title="Edit user" title="Edit user"
@@ -200,6 +202,7 @@ const Users = () => {
<Edit className="h-4 w-4" /> <Edit className="h-4 w-4" />
</button> </button>
<button <button
type="button"
onClick={() => handleResetPassword(user)} onClick={() => handleResetPassword(user)}
className="text-blue-400 hover:text-blue-600 dark:text-blue-500 dark:hover:text-blue-300 disabled:text-gray-300 disabled:cursor-not-allowed" className="text-blue-400 hover:text-blue-600 dark:text-blue-500 dark:hover:text-blue-300 disabled:text-gray-300 disabled:cursor-not-allowed"
title={ title={
@@ -212,6 +215,7 @@ const Users = () => {
<Key className="h-4 w-4" /> <Key className="h-4 w-4" />
</button> </button>
<button <button
type="button"
onClick={() => handleDeleteUser(user.id, user.username)} onClick={() => handleDeleteUser(user.id, user.username)}
className="text-danger-400 hover:text-danger-600 dark:text-danger-500 dark:hover:text-danger-400 disabled:text-gray-300 disabled:cursor-not-allowed" className="text-danger-400 hover:text-danger-600 dark:text-danger-500 dark:hover:text-danger-400 disabled:text-gray-300 disabled:cursor-not-allowed"
title={ title={