Update
This commit is contained in:
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
@@ -32,8 +32,8 @@
|
|||||||
<!-- Nepcha Analytics (nepcha.com) -->
|
<!-- Nepcha Analytics (nepcha.com) -->
|
||||||
<!-- Nepcha is a easy-to-use web analytics. No cookies and fully compliant with GDPR, CCPA and PECR. -->
|
<!-- 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 defer data-site="YOUR_DOMAIN_HERE" src="https://api.nepcha.com/js/nepcha-analytics.js"></script>
|
||||||
<script type="module" crossorigin src="/assets/index-5ba27364.js"></script>
|
<script type="module" crossorigin src="/assets/index-ad90a034.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-9492c046.css">
|
<link rel="stylesheet" href="/assets/index-71775912.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ import {
|
|||||||
Progress,
|
Progress,
|
||||||
Collapse,
|
Collapse,
|
||||||
Button,
|
Button,
|
||||||
ButtonGroup
|
ButtonGroup,
|
||||||
|
Select,
|
||||||
|
Option,
|
||||||
|
Input
|
||||||
} from "@material-tailwind/react";
|
} from "@material-tailwind/react";
|
||||||
import { EllipsisVerticalIcon } from "@heroicons/react/24/outline";
|
|
||||||
import { authorsTableData, projectsTableData } from "@/data";
|
|
||||||
|
|
||||||
const STATUS_COLORS = {
|
const STATUS_COLORS = {
|
||||||
success: "text-green-400",
|
success: "text-green-400",
|
||||||
@@ -563,255 +564,227 @@ export function Logs() {
|
|||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const toggleOpen = () => setOpen((cur) => !cur);
|
const toggleOpen = () => setOpen((cur) => !cur);
|
||||||
return (
|
return (
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className="mt-12 mb-8 flex flex-col gap-12">
|
<div className="mt-12 mb-8 flex flex-col gap-12">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader variant="gradient" color="gray" className="p-6 pt-2 pb-2">
|
<CardHeader variant="gradient" color="gray" className="p-6 pt-2 pb-2">
|
||||||
<Typography variant="h6" color="white">
|
<Typography variant="h6" color="white">
|
||||||
<button onClick={toggleOpen}>Filter und Optionen</button>
|
<button
|
||||||
|
onClick={handleToggleFilters}
|
||||||
|
className="flex w-full items-center justify-between"
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<span>Filter und Optionen</span>
|
||||||
|
{activeFilterCount > 0 && (
|
||||||
|
|
||||||
|
<span className="rounded-full bg-blue-gray-500/80 px-2 py-0.5 text-xs text-white">
|
||||||
|
{activeFilterCount} aktiv
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs uppercase tracking-wide text-gray-400">
|
||||||
|
{filtersOpen ? "Ausblenden" : "Anzeigen"}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</Typography>
|
</Typography>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<div className="flex flex-wrap mb-2">
|
{filtersOpen && (
|
||||||
<span className=" rounded-full bg-blue-gray-500/80 px-2 py-0.5 text-xs text-white">
|
<div>
|
||||||
{activeFilterCount} aktiv
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<Collapse open={open}>
|
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleExport('txt')}
|
onClick={() => handleExport('txt')}
|
||||||
disabled={actionLoading || loading}
|
disabled={actionLoading || loading}
|
||||||
className="w-full md:flex-1">
|
className="w-full md:flex-1">
|
||||||
Export TXT</Button>
|
Export TXT</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleExport('sql')}
|
onClick={() => handleExport('sql')}
|
||||||
disabled={actionLoading || loading}
|
disabled={actionLoading || loading}
|
||||||
className="w-full md:flex-1">
|
className="w-full md:flex-1">
|
||||||
Export SQL</Button>
|
Export SQL</Button>
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={handleDeleteFiltered}
|
onClick={handleDeleteFiltered}
|
||||||
disabled={actionLoading || loading || logs.length === 0}
|
disabled={actionLoading || loading || logs.length === 0}
|
||||||
className="w-full md:flex-1">
|
className="w-full md:flex-1">
|
||||||
Angezeigte löschen</Button>
|
Angezeigte löschen</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-2 mt-5">
|
|
||||||
|
|
||||||
<div className="grid gap-4 md:flex-1 lg:grid-cols-4">
|
<div className="flex flex-wrap gap-2 mt-10">
|
||||||
<div>
|
<div className="grid gap-4 flex-1">
|
||||||
<label className="mb-2 block text-sm font-medium text-blue-gray-600">Stack</label>
|
<Select
|
||||||
<select
|
|
||||||
multiple
|
multiple
|
||||||
value={selectedStacks}
|
value={selectedStacks}
|
||||||
onChange={handleMultiSelectChange(setSelectedStacks)}
|
onChange={handleMultiSelectChange(setSelectedStacks)}
|
||||||
className="w-full min-h-[8rem] rounded-md border border-gray-500 px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
|
className="text-gray-500"
|
||||||
|
variant="static"
|
||||||
|
label="Stacks"
|
||||||
>
|
>
|
||||||
{stackSelectOptions.map(({ value, label }) => (
|
{stackSelectOptions.map(({ value, label }) => (
|
||||||
<option
|
<option
|
||||||
key={value}
|
key={value}
|
||||||
value={value}
|
value={value}
|
||||||
onMouseDown={(event) => handleOptionMouseDown(event, selectedStacks, setSelectedStacks)}
|
onMouseDown={(event) => handleOptionMouseDown(event, selectedStacks, setSelectedStacks)}
|
||||||
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
|
className={`text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</Select>
|
||||||
|
|
||||||
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
|
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
|
||||||
<div className="flex flex-wrap gap-2">
|
{selectedStacks.length === 0 ? (
|
||||||
{selectedStacks.length === 0 ? (
|
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
|
||||||
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
|
Alle Stacks
|
||||||
Alle Stacks
|
</span>
|
||||||
</span>
|
) : (
|
||||||
) : (
|
<div className="flex flex-wrap gap-2">
|
||||||
<div className="flex flex-wrap gap-2">
|
{selectedStacks.map((stackId) => (
|
||||||
{selectedStacks.map((stackId) => (
|
<span
|
||||||
<span
|
key={stackId}
|
||||||
key={stackId}
|
className="rounded-full bg-purple-500/80 px-2 py-0.5 text-white"
|
||||||
className="rounded-full bg-purple-500/80 px-2 py-0.5 text-white"
|
>
|
||||||
>
|
{stackLabelMap.get(stackId) ?? `Stack ${stackId}`}
|
||||||
{stackLabelMap.get(stackId) ?? `Stack ${stackId}`}
|
</span>
|
||||||
</span>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="grid gap-4 flex-1">
|
||||||
<div>
|
<Select
|
||||||
<label className="mb-2 block text-sm font-medium text-blue-gray-600">Status</label>
|
|
||||||
<select
|
|
||||||
multiple
|
multiple
|
||||||
value={selectedStatuses}
|
value={selectedStatuses}
|
||||||
onChange={handleMultiSelectChange(setSelectedStatuses)}
|
onChange={handleMultiSelectChange(setSelectedStatuses)}
|
||||||
className="w-full min-h-[8rem] rounded-md border border-gray-500 px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
|
className="text-gray-500"
|
||||||
|
variant="static"
|
||||||
|
label="Status"
|
||||||
>
|
>
|
||||||
{statusSelectOptions.map(({ value, label }) => (
|
{statusSelectOptions.map(({ value, label }) => (
|
||||||
<option
|
<option
|
||||||
key={value}
|
key={value}
|
||||||
value={value}
|
value={value}
|
||||||
onMouseDown={(event) => handleOptionMouseDown(event, selectedStatuses, setSelectedStatuses)}
|
onMouseDown={(event) => handleOptionMouseDown(event, selectedStatuses, setSelectedStatuses)}
|
||||||
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
|
className={`text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</Select>
|
||||||
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
|
<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">
|
||||||
{selectedStatuses.length === 0 ? (
|
Alle Status
|
||||||
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
|
</span>
|
||||||
Alle Status
|
) : (
|
||||||
</span>
|
<div className="flex flex-wrap gap-2">
|
||||||
) : (
|
{selectedStatuses.map((status) => (
|
||||||
<div className="flex flex-wrap gap-2">
|
<span
|
||||||
{selectedStatuses.map((status) => (
|
key={status}
|
||||||
<span
|
className="rounded-full bg-brown-500/80 px-2 py-0.5 text-white"
|
||||||
key={status}
|
>
|
||||||
className="rounded-full bg-brown-500/80 px-2 py-0.5 text-white"
|
{status}
|
||||||
>
|
</span>
|
||||||
{status}
|
))}
|
||||||
</span>
|
</div>
|
||||||
))}
|
)}
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="grid gap-4 flex-1">
|
||||||
<div>
|
<Select
|
||||||
<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 border-gray-500 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/80 px-2 py-0.5 text-white"
|
|
||||||
>
|
|
||||||
{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
|
multiple
|
||||||
value={selectedRedeployTypes}
|
value={selectedRedeployTypes}
|
||||||
onChange={handleMultiSelectChange(setSelectedRedeployTypes)}
|
onChange={handleMultiSelectChange(setSelectedRedeployTypes)}
|
||||||
className="w-full min-h-[8rem] rounded-md border border-gray-500 px-3 py-2 text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
|
className="text-gray-500"
|
||||||
|
variant="static"
|
||||||
|
label="Redeploy-Typ"
|
||||||
>
|
>
|
||||||
{redeployTypeSelectOptions.map(({ value, label }) => (
|
{redeployTypeSelectOptions.map(({ value, label }) => (
|
||||||
<option
|
<option
|
||||||
key={value}
|
key={value}
|
||||||
value={value}
|
value={value}
|
||||||
onMouseDown={(event) => handleOptionMouseDown(event, selectedRedeployTypes, setSelectedRedeployTypes)}
|
onMouseDown={(event) => handleOptionMouseDown(event, selectedRedeployTypes, setSelectedRedeployTypes)}
|
||||||
className={`bg-white text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
|
className={`text-black-600 ${value === ALL_OPTION_VALUE ? 'font-semibold text-black-800' : ''}`}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</Select>
|
||||||
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
|
<div className="mt-2 min-h-[1.5rem] text-xs text-gray-400">
|
||||||
<div className="flex flex-wrap gap-2">
|
{selectedRedeployTypes.length === 0 ? (
|
||||||
{selectedRedeployTypes.length === 0 ? (
|
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
|
||||||
<span className="rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300">
|
Alle Typen
|
||||||
Alle Typen
|
</span>
|
||||||
</span>
|
) : (
|
||||||
) : (
|
<div className="flex flex-wrap gap-2">
|
||||||
<div className="flex flex-wrap gap-2">
|
{selectedRedeployTypes.map((type) => (
|
||||||
{selectedRedeployTypes.map((type) => (
|
<span
|
||||||
<span
|
key={type}
|
||||||
key={type}
|
className="rounded-full bg-teal-500/80 px-2 py-0.5 text-white"
|
||||||
className="rounded-full bg-teal-500/80 px-2 py-0.5 text-white"
|
>
|
||||||
>
|
{REDEPLOY_TYPE_LABELS[type] ?? type}
|
||||||
{REDEPLOY_TYPE_LABELS[type] ?? type}
|
</span>
|
||||||
</span>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="grid gap-4 flex-1">
|
||||||
<div className="md:col-span-2 lg:col-span-4">
|
<Select
|
||||||
<label className="mb-2 block text-sm font-medium text-gray-300">Nachricht (Freitext)</label>
|
multiple
|
||||||
<input
|
value={selectedEndpoints}
|
||||||
type="text"
|
onChange={handleMultiSelectChange(setSelectedRedeployTypes)}
|
||||||
|
className="text-gray-500"
|
||||||
|
variant="static"
|
||||||
|
label="Endpoints"
|
||||||
|
>
|
||||||
|
{endpointSelectOptions.map(({ value, label }) => (
|
||||||
|
<option
|
||||||
|
key={value}
|
||||||
|
value={value}
|
||||||
|
onMouseDown={(event) => handleOptionMouseDown(event, selectedEndpoints, setSelectedEndpoints)}
|
||||||
|
className={`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">
|
||||||
|
{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/80 px-2 py-0.5 text-white"
|
||||||
|
>
|
||||||
|
{endpoint}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-2 mt-10">
|
||||||
|
<div className="grid gap-4 flex-1">
|
||||||
|
<Input
|
||||||
value={messageQuery}
|
value={messageQuery}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
setMessageQuery(event.target.value);
|
setMessageQuery(event.target.value);
|
||||||
setPage(1);
|
setPage(1);
|
||||||
}}
|
}}
|
||||||
placeholder="Textsuche in Log-Nachrichten..."
|
variant="static"
|
||||||
className="w-full rounded-md border border-gray-500 bg-white px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500"
|
label="Nachricht (Freitext)"
|
||||||
/>
|
placeholder="Suche" />
|
||||||
</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 border-gray-500 bg-white 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-500 bg-white px-3 py-2 text-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Collapse>
|
|
||||||
|
)}
|
||||||
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user