This commit is contained in:
root
2025-10-16 10:11:52 +00:00
parent 4266adc853
commit 7de4e85a38
5 changed files with 290 additions and 36 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -32,8 +32,8 @@
<!-- Nepcha Analytics (nepcha.com) -->
<!-- Nepcha is a easy-to-use web analytics. No cookies and fully compliant with GDPR, CCPA and PECR. -->
<script defer data-site="YOUR_DOMAIN_HERE" src="https://api.nepcha.com/js/nepcha-analytics.js"></script>
<script type="module" crossorigin src="/assets/index-a934cea9.js"></script>
<link rel="stylesheet" href="/assets/index-987e6ee6.css">
<script type="module" crossorigin src="/assets/index-ca512e41.js"></script>
<link rel="stylesheet" href="/assets/index-72b21cb9.css">
</head>
<body>
<div id="root"></div>
+259 -5
View File
@@ -9,6 +9,9 @@ import {
Chip,
Tooltip,
Progress,
Collapse,
Button,
ButtonGroup
} from "@material-tailwind/react";
import { EllipsisVerticalIcon } from "@heroicons/react/24/outline";
import { authorsTableData, projectsTableData } from "@/data";
@@ -407,10 +410,6 @@ export function Logs() {
setFiltersOpen((prev) => !prev);
};
const handleRefresh = () => {
setRefreshSignal((prev) => prev + 1);
};
const handlePerPageChange = (event) => {
const value = event.target.value;
if (!VALID_PER_PAGE_VALUES.has(value)) return;
@@ -558,10 +557,265 @@ export function Logs() {
} finally {
setActionLoading(false);
}
};
};
const [open, setOpen] = React.useState(false);
const toggleOpen = () => setOpen((cur) => !cur);
return (
<div className="mt-12 mb-8 flex flex-col gap-12">
<Card>
<CardHeader variant="gradient" color="gray" className="p-6 pt-2 pb-2">
<Typography variant="h6" color="white">
<button onClick={toggleOpen}>Filter und Optionen</button>
</Typography>
</CardHeader>
<CardBody>
<div className="flex flex-wrap mb-2">
<span className=" rounded-full bg-blue-500/20 px-2 py-0.5 text-xs text-blue-300">
{activeFilterCount} aktiv
</span>
</div>
<Collapse open={open}>
<div className="flex flex-wrap gap-2">
<Button
onClick={() => handleExport('txt')}
disabled={actionLoading || loading}
className="w-full md:flex-1">
Export TXT</Button>
<Button
onClick={() => handleExport('sql')}
disabled={actionLoading || loading}
className="w-full md:flex-1">
Export SQL</Button>
<Button
color="red"
onClick={handleDeleteFiltered}
disabled={actionLoading || loading || logs.length === 0}
className="w-full md:flex-1">
Angezeigte löschen</Button>
</div>
<div className="flex flex-wrap gap-2 mt-5">
<div className="grid gap-4 md:flex-1 lg:grid-cols-4">
<div>
<label className="mb-2 block text-sm font-medium text-blue-gray-600">Stack</label>
<select
multiple
value={selectedStacks}
onChange={handleMultiSelectChange(setSelectedStacks)}
className="w-full min-h-[8rem] rounded-md border px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
{stackSelectOptions.map(({ value, label }) => (
<option
key={value}
value={value}
onMouseDown={(event) => handleOptionMouseDown(event, selectedStacks, setSelectedStacks)}
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
>
{label}
</option>
))}
</select>
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
<div className="flex flex-wrap gap-2">
{selectedStacks.length === 0 ? (
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
Alle Stacks
</span>
) : (
<div className="flex flex-wrap gap-2">
{selectedStacks.map((stackId) => (
<span
key={stackId}
className="rounded-full bg-purple-500/20 px-2 py-0.5 text-purple-200"
>
{stackLabelMap.get(stackId) ?? `Stack ${stackId}`}
</span>
))}
</div>
)}
</div>
</div>
</div>
<div>
<label className="mb-2 block text-sm font-medium text-blue-gray-600">Status</label>
<select
multiple
value={selectedStatuses}
onChange={handleMultiSelectChange(setSelectedStatuses)}
className="w-full min-h-[8rem] rounded-md border px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
{statusSelectOptions.map(({ value, label }) => (
<option
key={value}
value={value}
onMouseDown={(event) => handleOptionMouseDown(event, selectedStatuses, setSelectedStatuses)}
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
>
{label}
</option>
))}
</select>
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
<div className="flex flex-wrap gap-2">
{selectedStatuses.length === 0 ? (
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
Alle Status
</span>
) : (
<div className="flex flex-wrap gap-2">
{selectedStatuses.map((status) => (
<span
key={status}
className="rounded-full bg-amber-500/20 px-2 py-0.5 text-amber-200"
>
{status}
</span>
))}
</div>
)}
</div>
</div>
</div>
<div>
<label className="mb-2 block text-sm font-medium text-blue-gray-600">Endpoint</label>
<select
multiple
value={selectedEndpoints}
onChange={handleMultiSelectChange(setSelectedEndpoints)}
className="w-full min-h-[8rem] rounded-md border px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
{endpointSelectOptions.map(({ value, label }) => (
<option
key={value}
value={value}
onMouseDown={(event) => handleOptionMouseDown(event, selectedEndpoints, setSelectedEndpoints)}
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
>
{label}
</option>
))}
</select>
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
<div className="flex flex-wrap gap-2">
{selectedEndpoints.length === 0 ? (
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
Alle Endpoints
</span>
) : (
<div className="flex flex-wrap gap-2">
{selectedEndpoints.map((endpoint) => (
<span
key={endpoint}
className="rounded-full bg-blue-500/20 px-2 py-0.5 text-blue-200"
>
{endpoint}
</span>
))}
</div>
)}
</div>
</div>
</div>
<div>
<label className="mb-2 block text-sm font-medium text-blue-gray-600">Redeploy-Typ</label>
<select
multiple
value={selectedRedeployTypes}
onChange={handleMultiSelectChange(setSelectedRedeployTypes)}
className="w-full min-h-[8rem] rounded-md border px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
{redeployTypeSelectOptions.map(({ value, label }) => (
<option
key={value}
value={value}
onMouseDown={(event) => handleOptionMouseDown(event, selectedRedeployTypes, setSelectedRedeployTypes)}
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
>
{label}
</option>
))}
</select>
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
<div className="flex flex-wrap gap-2">
{selectedRedeployTypes.length === 0 ? (
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
Alle Typen
</span>
) : (
<div className="flex flex-wrap gap-2">
{selectedRedeployTypes.map((type) => (
<span
key={type}
className="rounded-full bg-teal-500/20 px-2 py-0.5 text-teal-200"
>
{REDEPLOY_TYPE_LABELS[type] ?? type}
</span>
))}
</div>
)}
</div>
</div>
</div>
<div className="md:col-span-2 lg:col-span-4">
<label className="mb-2 block text-sm font-medium text-gray-300">Nachricht (Freitext)</label>
<input
type="text"
value={messageQuery}
onChange={(event) => {
setMessageQuery(event.target.value);
setPage(1);
}}
placeholder="Textsuche in Log-Nachrichten..."
className="w-full rounded-md border border-gray-700 bg-gray-900/70 px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500"
/>
</div>
<div>
<label className="mb-2 block text-sm font-medium text-gray-300">Von</label>
<input
type="datetime-local"
value={fromDate}
onChange={(event) => {
setFromDate(event.target.value);
setPage(1);
}}
className="w-full rounded-md border border-gray-700 bg-gray-900/70 px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500"
/>
</div>
<div>
<label className="mb-2 block text-sm font-medium text-gray-300">Bis</label>
<input
type="datetime-local"
value={toDate}
onChange={(event) => {
setToDate(event.target.value);
setPage(1);
}}
className="w-full rounded-md border border-gray-700 bg-gray-900/70 px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500"
/>
</div>
</div>
</div>
</Collapse>
</CardBody>
</Card>
<Card>
<CardHeader variant="gradient" color="gray" className="mb-8 p-6">
<Typography variant="h6" color="white">