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>
<button
type="button"
onClick={() => onToggle(card.cardId)}
className={`flex items-center gap-1 px-2 py-1 rounded text-xs font-medium transition-colors ${
card.enabled
@@ -271,6 +272,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
</h3>
</div>
<button
type="button"
onClick={onClose}
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">
<button
type="button"
onClick={handleSave}
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 ${
@@ -336,6 +339,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
</button>
<button
type="button"
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"
>
@@ -344,6 +348,7 @@ const DashboardSettingsModal = ({ isOpen, onClose }) => {
</button>
<button
type="button"
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"
>

View File

@@ -102,6 +102,7 @@ const InlineEdit = ({
} ${isLoading ? "opacity-50" : ""}`}
/>
<button
type="button"
onClick={handleSave}
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"
@@ -110,6 +111,7 @@ const InlineEdit = ({
<Check className="h-4 w-4" />
</button>
<button
type="button"
onClick={handleCancel}
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"
@@ -145,6 +147,7 @@ const InlineEdit = ({
{displayValue}
{!disabled && (
<button
type="button"
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"
title="Edit"

View File

@@ -221,6 +221,7 @@ const InlineGroupEdit = ({
)}
</div>
<button
type="button"
onClick={handleSave}
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"
@@ -229,6 +230,7 @@ const InlineGroupEdit = ({
<Check className="h-4 w-4" />
</button>
<button
type="button"
onClick={handleCancel}
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"
@@ -256,6 +258,7 @@ const InlineGroupEdit = ({
</span>
{!disabled && (
<button
type="button"
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"
title="Edit group"

View File

@@ -386,6 +386,7 @@ const Layout = ({ children }) => {
{subItem.name}
</span>
<button
type="button"
onClick={(e) => {
e.preventDefault();
setSidebarOpen(false);
@@ -453,6 +454,7 @@ const Layout = ({ children }) => {
>
{sidebarCollapsed ? (
<button
type="button"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="flex items-center justify-center w-8 h-8 rounded-md hover:bg-secondary-100 transition-colors"
title="Expand sidebar"
@@ -468,6 +470,7 @@ const Layout = ({ children }) => {
</h1>
</div>
<button
type="button"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="flex items-center justify-center w-8 h-8 rounded-md hover:bg-secondary-100 transition-colors"
title="Collapse sidebar"
@@ -549,6 +552,7 @@ const Layout = ({ children }) => {
)}
{!sidebarCollapsed && (
<button
type="button"
onClick={(e) => {
e.preventDefault();
handleAddHost();
@@ -659,6 +663,7 @@ const Layout = ({ children }) => {
</div>
</Link>
<button
type="button"
onClick={handleLogout}
className="ml-2 p-1.5 text-secondary-400 hover:text-secondary-600 hover:bg-secondary-100 rounded transition-colors"
title="Sign out"
@@ -675,6 +680,7 @@ const Layout = ({ children }) => {
Updated: {formatRelativeTimeShort(stats.lastUpdated)}
</span>
<button
type="button"
onClick={() => refetch()}
disabled={isFetching}
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" />
</Link>
<button
type="button"
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"
title="Sign out"
@@ -717,6 +724,7 @@ const Layout = ({ children }) => {
{stats && (
<div className="flex flex-col items-center py-1 border-t border-secondary-200 dark:border-secondary-700">
<button
type="button"
onClick={() => refetch()}
disabled={isFetching}
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"}
</p>
<button
type="button"
onClick={() => refetch()}
className="mt-2 btn-danger text-xs"
>
@@ -1010,6 +1011,7 @@ const Dashboard = () => {
</div>
<div className="flex items-center gap-3">
<button
type="button"
onClick={() => setShowSettingsModal(true)}
className="btn-outline flex items-center gap-2"
title="Customize dashboard layout"
@@ -1018,6 +1020,7 @@ const Dashboard = () => {
Customize Dashboard
</button>
<button
type="button"
onClick={() => refetch()}
disabled={isFetching}
className="btn-outline flex items-center gap-2"

View File

@@ -163,6 +163,7 @@ const HostDetail = () => {
{error.message || "Failed to load host details"}
</p>
<button
type="button"
onClick={() => refetch()}
className="mt-2 btn-danger text-xs"
>
@@ -257,6 +258,7 @@ const HostDetail = () => {
</div>
<div className="flex items-center gap-2">
<button
type="button"
onClick={() => refetch()}
disabled={isFetching}
className="btn-outline flex items-center gap-2 text-sm"
@@ -268,6 +270,7 @@ const HostDetail = () => {
{isFetching ? "Refreshing..." : "Refresh"}
</button>
<button
type="button"
onClick={() => setShowCredentialsModal(true)}
className="btn-outline flex items-center gap-2 text-sm"
>
@@ -275,6 +278,7 @@ const HostDetail = () => {
Deploy Agent
</button>
<button
type="button"
onClick={() => setShowDeleteModal(true)}
className="btn-danger flex items-center gap-2 text-sm"
>
@@ -292,6 +296,7 @@ const HostDetail = () => {
<div className="card">
<div className="flex border-b border-secondary-200 dark:border-secondary-600">
<button
type="button"
onClick={() => handleTabChange("host")}
className={`px-4 py-2 text-sm font-medium ${
activeTab === "host"
@@ -302,6 +307,7 @@ const HostDetail = () => {
Host Info
</button>
<button
type="button"
onClick={() => handleTabChange("network")}
className={`px-4 py-2 text-sm font-medium ${
activeTab === "network"
@@ -312,6 +318,7 @@ const HostDetail = () => {
Network
</button>
<button
type="button"
onClick={() => handleTabChange("system")}
className={`px-4 py-2 text-sm font-medium ${
activeTab === "system"
@@ -322,6 +329,7 @@ const HostDetail = () => {
System
</button>
<button
type="button"
onClick={() => handleTabChange("monitoring")}
className={`px-4 py-2 text-sm font-medium ${
activeTab === "monitoring"
@@ -332,6 +340,7 @@ const HostDetail = () => {
Resource
</button>
<button
type="button"
onClick={() => handleTabChange("history")}
className={`px-4 py-2 text-sm font-medium ${
activeTab === "history"
@@ -427,6 +436,7 @@ const HostDetail = () => {
Auto-update
</span>
<button
type="button"
onClick={() =>
toggleAutoUpdateMutation.mutate(!host.auto_update)
}
@@ -862,6 +872,7 @@ const HostDetail = () => {
{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">
<button
type="button"
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"
>
@@ -906,6 +917,7 @@ const HostDetail = () => {
<div className="p-4">
<div className="grid grid-cols-3 gap-4">
<button
type="button"
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"
title="View all packages for this host"
@@ -922,6 +934,7 @@ const HostDetail = () => {
</button>
<button
type="button"
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"
title="View outdated packages for this host"
@@ -938,6 +951,7 @@ const HostDetail = () => {
</button>
<button
type="button"
onClick={() =>
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}
</h3>
<button
type="button"
onClick={onClose}
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">
<nav className="-mb-px flex space-x-8">
<button
type="button"
onClick={() => setActiveTab("quick-install")}
className={`py-2 px-1 border-b-2 font-medium text-sm ${
activeTab === "quick-install"
@@ -1104,6 +1120,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
Quick Install
</button>
<button
type="button"
onClick={() => setActiveTab("credentials")}
className={`py-2 px-1 border-b-2 font-medium text-sm ${
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"
/>
<button
type="button"
onClick={() =>
copyToClipboard(
`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"
/>
<button
type="button"
onClick={() =>
copyToClipboard(
`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"
/>
<button
type="button"
onClick={() =>
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",
@@ -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"
/>
<button
type="button"
onClick={() =>
copyToClipboard(
`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"
/>
<button
type="button"
onClick={() =>
copyToClipboard(
"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"
/>
<button
type="button"
onClick={() =>
copyToClipboard(
"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"
/>
<button
type="button"
onClick={() =>
copyToClipboard(
`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"
/>
<button
type="button"
onClick={() => copyToClipboard(host.api_id)}
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"
/>
<button
type="button"
onClick={() => setShowApiKey(!showApiKey)}
className="btn-outline flex items-center gap-1"
>
@@ -1360,6 +1386,7 @@ echo " - View logs: tail -f /var/log/patchmon-agent.log"`;
)}
</button>
<button
type="button"
onClick={() => copyToClipboard(host.api_key)}
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">
<button onClick={onClose} className="btn-primary">
<button type="button" onClick={onClose} className="btn-primary">
Close
</button>
</div>
@@ -1441,6 +1468,7 @@ const DeleteConfirmationModal = ({
<div className="flex justify-end gap-3">
<button
type="button"
onClick={onClose}
className="btn-outline"
disabled={isLoading}
@@ -1448,6 +1476,7 @@ const DeleteConfirmationModal = ({
Cancel
</button>
<button
type="button"
onClick={onConfirm}
className="btn-danger"
disabled={isLoading}

View File

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

View File

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

View File

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

View File

@@ -272,6 +272,7 @@ const Packages = () => {
pkg.affectedHostsCount || pkg.affectedHosts?.length || 0;
return (
<button
type="button"
onClick={() => handleAffectedHostsClick(pkg)}
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`}
@@ -354,6 +355,7 @@ const Packages = () => {
{error.message || "Failed to load packages"}
</p>
<button
type="button"
onClick={() => refetch()}
className="mt-2 btn-danger text-xs"
>
@@ -380,6 +382,7 @@ const Packages = () => {
</div>
<div className="flex items-center gap-3">
<button
type="button"
onClick={() => refetch()}
disabled={isFetching}
className="btn-outline flex items-center gap-2"
@@ -524,6 +527,7 @@ const Packages = () => {
{/* Columns Button */}
<div className="flex items-center">
<button
type="button"
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"
>
@@ -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"
>
<button
type="button"
onClick={() => handleSort(column.id)}
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
</h3>
<button
type="button"
onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
>
@@ -672,6 +678,7 @@ const ColumnSettingsModal = ({
</span>
</div>
<button
type="button"
onClick={() => onToggleVisibility(column.id)}
className={`p-1 rounded ${
column.visible
@@ -691,12 +698,14 @@ const ColumnSettingsModal = ({
<div className="flex justify-between mt-6">
<button
type="button"
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"
>
Reset to Default
</button>
<button
type="button"
onClick={onClose}
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 space-x-3">
<button
type="button"
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"
>
@@ -115,6 +116,7 @@ const Permissions = () => {
Refresh Permissions
</button>
<button
type="button"
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"
>
@@ -265,6 +267,7 @@ const RolePermissionsCard = ({
{isEditing ? (
<>
<button
type="button"
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"
>
@@ -272,6 +275,7 @@ const RolePermissionsCard = ({
Save
</button>
<button
type="button"
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"
>
@@ -282,6 +286,7 @@ const RolePermissionsCard = ({
) : (
<>
<button
type="button"
onClick={onEdit}
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"
@@ -291,6 +296,7 @@ const RolePermissionsCard = ({
</button>
{!isBuiltInRole && (
<button
type="button"
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"
>

View File

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

View File

@@ -238,6 +238,7 @@ const Repositories = () => {
</div>
<div className="flex items-center gap-3">
<button
type="button"
onClick={() => refetch()}
disabled={isFetching}
className="btn-outline flex items-center gap-2"
@@ -363,6 +364,7 @@ const Repositories = () => {
{/* Columns Button */}
<div className="flex items-center">
<button
type="button"
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"
>
@@ -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"
>
<button
type="button"
onClick={() => handleSort(column.id)}
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
</h3>
<button
type="button"
onClick={onClose}
className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-500 dark:hover:text-secondary-300"
>
@@ -591,6 +595,7 @@ const ColumnSettingsModal = ({
</span>
</div>
<button
type="button"
onClick={() => onToggleVisibility(column.id)}
className={`w-4 h-4 rounded border-2 flex items-center justify-center ${
column.visible
@@ -606,12 +611,14 @@ const ColumnSettingsModal = ({
<div className="flex justify-between mt-6">
<button
type="button"
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"
>
Reset to Default
</button>
<button
type="button"
onClick={onClose}
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 ? (
<>
<button
type="button"
onClick={handleCancel}
className="btn-outline"
disabled={updateRepositoryMutation.isPending}
@@ -168,6 +169,7 @@ const RepositoryDetail = () => {
Cancel
</button>
<button
type="button"
onClick={handleSave}
className="btn-primary"
disabled={updateRepositoryMutation.isPending}
@@ -178,7 +180,7 @@ const RepositoryDetail = () => {
</button>
</>
) : (
<button onClick={handleEdit} className="btn-primary">
<button type="button" onClick={handleEdit} className="btn-primary">
Edit Repository
</button>
)}

View File

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